blob: b298db674c73cd6fcb960d564329c95a15b18027 [file] [log] [blame]
Ian Rogers57b86d42012-03-27 16:05:41 -07001/*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Roland Levillain0d5a2812015-11-13 10:07:31 +000017#include <stdint.h>
18
Mathieu Chartierc7853442015-03-27 14:35:38 -070019#include "art_field-inl.h"
Mathieu Chartiere401d142015-04-22 13:56:20 -070020#include "art_method-inl.h"
Andreas Gampe8228cdf2017-05-30 15:03:54 -070021#include "base/callee_save_type.h"
Ian Rogers57b86d42012-03-27 16:05:41 -070022#include "callee_save_frame.h"
Ian Rogers4f6ad8a2013-03-18 15:27:28 -070023#include "dex_file-inl.h"
Mingyao Yang98d1cc82014-05-15 17:02:16 -070024#include "entrypoints/entrypoint_utils-inl.h"
Roland Levillain0d5a2812015-11-13 10:07:31 +000025#include "gc_root-inl.h"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080026#include "mirror/class-inl.h"
Roland Levillain0d5a2812015-11-13 10:07:31 +000027#include "mirror/object_reference.h"
Ian Rogers57b86d42012-03-27 16:05:41 -070028
29namespace art {
30
Mathieu Chartiera61347b2016-02-05 13:47:06 -080031inline constexpr bool FindFieldTypeIsRead(FindFieldType type) {
32 return type == InstanceObjectRead ||
33 type == InstancePrimitiveRead ||
34 type == StaticObjectRead ||
35 type == StaticPrimitiveRead;
36}
37
38// Helper function to do a null check after trying to resolve the field. Not for statics since obj
39// does not exist there. There is a suspend check, object is a double pointer to update the value
40// in the caller in case it moves.
Mathieu Chartierbf369182016-02-04 18:13:32 -080041template<FindFieldType type, bool kAccessCheck>
42ALWAYS_INLINE static inline ArtField* FindInstanceField(uint32_t field_idx,
43 ArtMethod* referrer,
44 Thread* self,
45 size_t size,
46 mirror::Object** obj)
47 REQUIRES(!Roles::uninterruptible_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -070048 REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartierbf369182016-02-04 18:13:32 -080049 StackHandleScope<1> hs(self);
50 HandleWrapper<mirror::Object> h(hs.NewHandleWrapper(obj));
51 ArtField* field = FindFieldFromCode<type, kAccessCheck>(field_idx, referrer, self, size);
Andreas Gampefa4333d2017-02-14 11:10:34 -080052 if (LIKELY(field != nullptr) && UNLIKELY(h == nullptr)) {
Mathieu Chartierbf369182016-02-04 18:13:32 -080053 ThrowNullPointerExceptionForFieldAccess(field, /*is_read*/FindFieldTypeIsRead(type));
54 return nullptr;
55 }
56 return field;
57}
58
Nicolas Geoffray5b3c6c02017-01-19 14:22:26 +000059static ArtMethod* GetReferrer(Thread* self) REQUIRES_SHARED(Locks::mutator_lock_) {
60 if (kIsDebugBuild) {
61 // stub_test doesn't call this code with a proper frame, so get the outer, and if
62 // it does not have compiled code return it.
Andreas Gampe8228cdf2017-05-30 15:03:54 -070063 ArtMethod* outer = GetCalleeSaveOuterMethod(self, CalleeSaveType::kSaveRefsOnly);
Nicolas Geoffray5b3c6c02017-01-19 14:22:26 +000064 if (outer->GetEntryPointFromQuickCompiledCode() == nullptr) {
65 return outer;
66 }
Fred Shih37f05ef2014-07-16 18:38:08 -070067 }
Andreas Gampe8228cdf2017-05-30 15:03:54 -070068 return GetCalleeSaveMethodCallerAndOuterMethod(self, CalleeSaveType::kSaveRefsOnly).caller;
Fred Shih37f05ef2014-07-16 18:38:08 -070069}
70
Nicolas Geoffray5b3c6c02017-01-19 14:22:26 +000071#define ART_GET_FIELD_FROM_CODE(Kind, PrimitiveType, RetType, SetType, \
72 PrimitiveOrObject, IsObject, Ptr) \
73 extern "C" RetType artGet ## Kind ## StaticFromCode(uint32_t field_idx, \
74 ArtMethod* referrer, \
75 Thread* self) \
76 REQUIRES_SHARED(Locks::mutator_lock_) { \
77 ScopedQuickEntrypointChecks sqec(self); \
78 ArtField* field = FindFieldFast( \
79 field_idx, referrer, Static ## PrimitiveOrObject ## Read, \
80 sizeof(PrimitiveType)); \
81 if (LIKELY(field != nullptr)) { \
82 return field->Get ## Kind (field->GetDeclaringClass())Ptr; \
83 } \
84 field = FindFieldFromCode<Static ## PrimitiveOrObject ## Read, true>( \
85 field_idx, referrer, self, sizeof(PrimitiveType)); \
86 if (LIKELY(field != nullptr)) { \
87 return field->Get ## Kind (field->GetDeclaringClass())Ptr; \
88 } \
89 /* Will throw exception by checking with Thread::Current. */ \
90 return 0; \
91 } \
92 \
93 extern "C" RetType artGet ## Kind ## InstanceFromCode(uint32_t field_idx, \
94 mirror::Object* obj, \
95 ArtMethod* referrer, \
96 Thread* self) \
97 REQUIRES_SHARED(Locks::mutator_lock_) { \
98 ScopedQuickEntrypointChecks sqec(self); \
99 ArtField* field = FindFieldFast( \
100 field_idx, referrer, Instance ## PrimitiveOrObject ## Read, \
101 sizeof(PrimitiveType)); \
102 if (LIKELY(field != nullptr) && obj != nullptr) { \
103 return field->Get ## Kind (obj)Ptr; \
104 } \
105 field = FindInstanceField<Instance ## PrimitiveOrObject ## Read, true>( \
106 field_idx, referrer, self, sizeof(PrimitiveType), &obj); \
107 if (LIKELY(field != nullptr)) { \
108 return field->Get ## Kind (obj)Ptr; \
109 } \
110 /* Will throw exception by checking with Thread::Current. */ \
111 return 0; \
112 } \
113 \
114 extern "C" int artSet ## Kind ## StaticFromCode(uint32_t field_idx, \
115 SetType new_value, \
116 ArtMethod* referrer, \
117 Thread* self) \
118 REQUIRES_SHARED(Locks::mutator_lock_) { \
119 ScopedQuickEntrypointChecks sqec(self); \
120 ArtField* field = FindFieldFast( \
121 field_idx, referrer, Static ## PrimitiveOrObject ## Write, \
122 sizeof(PrimitiveType)); \
123 if (LIKELY(field != nullptr)) { \
124 field->Set ## Kind <false>(field->GetDeclaringClass(), new_value); \
125 return 0; \
126 } \
127 if (IsObject) { \
128 StackHandleScope<1> hs(self); \
129 HandleWrapper<mirror::Object> h_obj(hs.NewHandleWrapper( \
130 reinterpret_cast<mirror::Object**>(&new_value))); \
131 field = FindFieldFromCode<Static ## PrimitiveOrObject ## Write, true>( \
132 field_idx, referrer, self, sizeof(PrimitiveType)); \
133 } else { \
134 field = FindFieldFromCode<Static ## PrimitiveOrObject ## Write, true>( \
135 field_idx, referrer, self, sizeof(PrimitiveType)); \
136 } \
137 if (LIKELY(field != nullptr)) { \
138 field->Set ## Kind <false>(field->GetDeclaringClass(), new_value); \
139 return 0; \
140 } \
141 return -1; \
142 } \
143 \
144 extern "C" int artSet ## Kind ## InstanceFromCode(uint32_t field_idx, \
145 mirror::Object* obj, \
146 SetType new_value, \
147 ArtMethod* referrer, \
148 Thread* self) \
149 REQUIRES_SHARED(Locks::mutator_lock_) { \
150 ScopedQuickEntrypointChecks sqec(self); \
151 ArtField* field = FindFieldFast( \
152 field_idx, referrer, Instance ## PrimitiveOrObject ## Write, \
153 sizeof(PrimitiveType)); \
154 if (LIKELY(field != nullptr && obj != nullptr)) { \
155 field->Set ## Kind <false>(obj, new_value); \
156 return 0; \
157 } \
158 if (IsObject) { \
159 StackHandleScope<1> hs(self); \
160 HandleWrapper<mirror::Object> h_obj(hs.NewHandleWrapper( \
161 reinterpret_cast<mirror::Object**>(&new_value))); \
162 field = FindInstanceField<Instance ## PrimitiveOrObject ## Write, true>( \
163 field_idx, \
164 referrer, \
165 self, \
166 sizeof(PrimitiveType), \
167 &obj); \
168 } else { \
169 field = FindInstanceField<Instance ## PrimitiveOrObject ## Write, true>( \
170 field_idx, \
171 referrer, \
172 self, \
173 sizeof(PrimitiveType), \
174 &obj); \
175 } \
176 if (LIKELY(field != nullptr)) { \
177 field->Set ## Kind<false>(obj, new_value); \
178 return 0; \
179 } \
180 return -1; \
181 } \
182 \
183 extern "C" RetType artGet ## Kind ## StaticFromCompiledCode( \
184 uint32_t field_idx, \
185 Thread* self) \
186 REQUIRES_SHARED(Locks::mutator_lock_) { \
187 return artGet ## Kind ## StaticFromCode( \
188 field_idx, GetReferrer(self), self); \
189 } \
190 \
191 extern "C" RetType artGet ## Kind ## InstanceFromCompiledCode( \
192 uint32_t field_idx, \
193 mirror::Object* obj, \
194 Thread* self) \
195 REQUIRES_SHARED(Locks::mutator_lock_) { \
196 return artGet ## Kind ## InstanceFromCode( \
197 field_idx, obj, GetReferrer(self), self); \
198 } \
199 \
200 extern "C" int artSet ## Kind ## StaticFromCompiledCode( \
201 uint32_t field_idx, \
202 SetType new_value, \
203 Thread* self) \
204 REQUIRES_SHARED(Locks::mutator_lock_) { \
205 return artSet ## Kind ## StaticFromCode( \
206 field_idx, new_value, GetReferrer(self), self); \
207 } \
208 \
209 extern "C" int artSet ## Kind ## InstanceFromCompiledCode( \
210 uint32_t field_idx, \
211 mirror::Object* obj, \
212 SetType new_value, \
213 Thread* self) \
214 REQUIRES_SHARED(Locks::mutator_lock_) { \
215 return artSet ## Kind ## InstanceFromCode( \
216 field_idx, obj, new_value, GetReferrer(self), self); \
217 }
218
219ART_GET_FIELD_FROM_CODE(Byte, int8_t, ssize_t, uint32_t, Primitive, false, )
220ART_GET_FIELD_FROM_CODE(Boolean, int8_t, size_t, uint32_t, Primitive, false, )
221ART_GET_FIELD_FROM_CODE(Short, int16_t, ssize_t, uint16_t, Primitive, false, )
222ART_GET_FIELD_FROM_CODE(Char, int16_t, size_t, uint16_t, Primitive, false, )
223ART_GET_FIELD_FROM_CODE(32, int32_t, size_t, uint32_t, Primitive, false, )
224ART_GET_FIELD_FROM_CODE(64, int64_t, uint64_t, uint64_t, Primitive, false, )
225ART_GET_FIELD_FROM_CODE(Obj, mirror::HeapReference<mirror::Object>, mirror::Object*,
226 mirror::Object*, Object, true, .Ptr())
227
228
229// To cut on the number of entrypoints, we have shared entries for
230// byte/boolean and char/short for setting an instance or static field. We just
231// forward those to the unsigned variant.
232extern "C" int artSet8StaticFromCompiledCode(uint32_t field_idx,
233 uint32_t new_value,
234 Thread* self)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700235 REQUIRES_SHARED(Locks::mutator_lock_) {
Nicolas Geoffray5b3c6c02017-01-19 14:22:26 +0000236 return artSetBooleanStaticFromCode(field_idx, new_value, GetReferrer(self), self);
Fred Shih37f05ef2014-07-16 18:38:08 -0700237}
238
Nicolas Geoffray5b3c6c02017-01-19 14:22:26 +0000239extern "C" int artSet16StaticFromCompiledCode(uint32_t field_idx,
240 uint16_t new_value,
Andreas Gampe67409972016-07-19 22:34:53 -0700241 Thread* self)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700242 REQUIRES_SHARED(Locks::mutator_lock_) {
Nicolas Geoffray5b3c6c02017-01-19 14:22:26 +0000243 return artSetCharStaticFromCode(field_idx, new_value, GetReferrer(self), self);
Fred Shih37f05ef2014-07-16 18:38:08 -0700244}
245
Nicolas Geoffray5b3c6c02017-01-19 14:22:26 +0000246extern "C" int artSet8InstanceFromCompiledCode(uint32_t field_idx,
Mathieu Chartierbf369182016-02-04 18:13:32 -0800247 mirror::Object* obj,
Nicolas Geoffray5b3c6c02017-01-19 14:22:26 +0000248 uint8_t new_value,
Mathieu Chartierbf369182016-02-04 18:13:32 -0800249 Thread* self)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700250 REQUIRES_SHARED(Locks::mutator_lock_) {
Nicolas Geoffray5b3c6c02017-01-19 14:22:26 +0000251 return artSetBooleanInstanceFromCode(field_idx, obj, new_value, GetReferrer(self), self);
Fred Shih37f05ef2014-07-16 18:38:08 -0700252}
253
Nicolas Geoffray5b3c6c02017-01-19 14:22:26 +0000254extern "C" int artSet16InstanceFromCompiledCode(uint32_t field_idx,
255 mirror::Object* obj,
256 uint16_t new_value,
257 Thread* self)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700258 REQUIRES_SHARED(Locks::mutator_lock_) {
Nicolas Geoffray5b3c6c02017-01-19 14:22:26 +0000259 return artSetCharInstanceFromCode(field_idx, obj, new_value, GetReferrer(self), self);
Ian Rogers57b86d42012-03-27 16:05:41 -0700260}
261
Mathieu Chartierbf369182016-02-04 18:13:32 -0800262extern "C" int artSet8StaticFromCode(uint32_t field_idx,
263 uint32_t new_value,
264 ArtMethod* referrer,
265 Thread* self)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700266 REQUIRES_SHARED(Locks::mutator_lock_) {
Nicolas Geoffray5b3c6c02017-01-19 14:22:26 +0000267 return artSetBooleanStaticFromCode(field_idx, new_value, referrer, self);
Fred Shih37f05ef2014-07-16 18:38:08 -0700268}
269
Mathieu Chartierbf369182016-02-04 18:13:32 -0800270extern "C" int artSet16StaticFromCode(uint32_t field_idx,
271 uint16_t new_value,
272 ArtMethod* referrer,
273 Thread* self)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700274 REQUIRES_SHARED(Locks::mutator_lock_) {
Nicolas Geoffray5b3c6c02017-01-19 14:22:26 +0000275 return artSetCharStaticFromCode(field_idx, new_value, referrer, self);
Ian Rogers57b86d42012-03-27 16:05:41 -0700276}
277
Mathieu Chartierbf369182016-02-04 18:13:32 -0800278extern "C" int artSet8InstanceFromCode(uint32_t field_idx,
279 mirror::Object* obj,
280 uint8_t new_value,
281 ArtMethod* referrer,
282 Thread* self)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700283 REQUIRES_SHARED(Locks::mutator_lock_) {
Nicolas Geoffray5b3c6c02017-01-19 14:22:26 +0000284 return artSetBooleanInstanceFromCode(field_idx, obj, new_value, referrer, self);
Fred Shih37f05ef2014-07-16 18:38:08 -0700285}
286
Mathieu Chartierbf369182016-02-04 18:13:32 -0800287extern "C" int artSet16InstanceFromCode(uint32_t field_idx,
288 mirror::Object* obj,
289 uint16_t new_value,
290 ArtMethod* referrer,
291 Thread* self)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700292 REQUIRES_SHARED(Locks::mutator_lock_) {
Nicolas Geoffray5b3c6c02017-01-19 14:22:26 +0000293 return artSetCharInstanceFromCode(field_idx, obj, new_value, referrer, self);
Ian Rogers57b86d42012-03-27 16:05:41 -0700294}
295
Roland Levillain7c1559a2015-12-15 10:55:36 +0000296extern "C" mirror::Object* artReadBarrierMark(mirror::Object* obj) {
297 DCHECK(kEmitCompilerReadBarrier);
298 return ReadBarrier::Mark(obj);
299}
300
Man Cao1aee9002015-07-14 22:31:42 -0700301extern "C" mirror::Object* artReadBarrierSlow(mirror::Object* ref ATTRIBUTE_UNUSED,
Roland Levillain0d5a2812015-11-13 10:07:31 +0000302 mirror::Object* obj,
303 uint32_t offset) {
Hans Boehmcc55e1d2017-07-27 15:28:07 -0700304 // Used only in connection with non-volatile loads.
Roland Levillain0d5a2812015-11-13 10:07:31 +0000305 DCHECK(kEmitCompilerReadBarrier);
Man Cao1aee9002015-07-14 22:31:42 -0700306 uint8_t* raw_addr = reinterpret_cast<uint8_t*>(obj) + offset;
307 mirror::HeapReference<mirror::Object>* ref_addr =
Roland Levillain0d5a2812015-11-13 10:07:31 +0000308 reinterpret_cast<mirror::HeapReference<mirror::Object>*>(raw_addr);
309 constexpr ReadBarrierOption kReadBarrierOption =
310 kUseReadBarrier ? kWithReadBarrier : kWithoutReadBarrier;
311 mirror::Object* result =
Hans Boehmcc55e1d2017-07-27 15:28:07 -0700312 ReadBarrier::Barrier<mirror::Object, /* kIsVolatile */ false, kReadBarrierOption>(
313 obj,
314 MemberOffset(offset),
315 ref_addr);
Roland Levillain0d5a2812015-11-13 10:07:31 +0000316 return result;
317}
318
319extern "C" mirror::Object* artReadBarrierForRootSlow(GcRoot<mirror::Object>* root) {
320 DCHECK(kEmitCompilerReadBarrier);
Roland Levillain0d5a2812015-11-13 10:07:31 +0000321 return root->Read();
Man Cao1aee9002015-07-14 22:31:42 -0700322}
323
Ian Rogers57b86d42012-03-27 16:05:41 -0700324} // namespace art