blob: 7d34d2402a56590ade893b3877ea7c39e14b1f09 [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
Roland Levillain809f5b12018-01-04 14:05:59 +000071// Macro used to define this set of functions:
72//
73// art{Get,Set}<Kind>{Static,Instance}FromCode
74// art{Get,Set}<Kind>{Static,Instance}FromCompiledCode
75//
Nicolas Geoffray5b3c6c02017-01-19 14:22:26 +000076#define ART_GET_FIELD_FROM_CODE(Kind, PrimitiveType, RetType, SetType, \
77 PrimitiveOrObject, IsObject, Ptr) \
78 extern "C" RetType artGet ## Kind ## StaticFromCode(uint32_t field_idx, \
79 ArtMethod* referrer, \
80 Thread* self) \
81 REQUIRES_SHARED(Locks::mutator_lock_) { \
82 ScopedQuickEntrypointChecks sqec(self); \
83 ArtField* field = FindFieldFast( \
84 field_idx, referrer, Static ## PrimitiveOrObject ## Read, \
85 sizeof(PrimitiveType)); \
86 if (LIKELY(field != nullptr)) { \
Andreas Gampe49fc60e2017-08-24 13:19:59 -070087 return field->Get ## Kind (field->GetDeclaringClass())Ptr; /* NOLINT */ \
Nicolas Geoffray5b3c6c02017-01-19 14:22:26 +000088 } \
89 field = FindFieldFromCode<Static ## PrimitiveOrObject ## Read, true>( \
90 field_idx, referrer, self, sizeof(PrimitiveType)); \
91 if (LIKELY(field != nullptr)) { \
Andreas Gampe49fc60e2017-08-24 13:19:59 -070092 return field->Get ## Kind (field->GetDeclaringClass())Ptr; /* NOLINT */ \
Nicolas Geoffray5b3c6c02017-01-19 14:22:26 +000093 } \
94 /* Will throw exception by checking with Thread::Current. */ \
95 return 0; \
96 } \
97 \
98 extern "C" RetType artGet ## Kind ## InstanceFromCode(uint32_t field_idx, \
99 mirror::Object* obj, \
100 ArtMethod* referrer, \
101 Thread* self) \
102 REQUIRES_SHARED(Locks::mutator_lock_) { \
103 ScopedQuickEntrypointChecks sqec(self); \
104 ArtField* field = FindFieldFast( \
105 field_idx, referrer, Instance ## PrimitiveOrObject ## Read, \
106 sizeof(PrimitiveType)); \
107 if (LIKELY(field != nullptr) && obj != nullptr) { \
Andreas Gampe49fc60e2017-08-24 13:19:59 -0700108 return field->Get ## Kind (obj)Ptr; /* NOLINT */ \
Nicolas Geoffray5b3c6c02017-01-19 14:22:26 +0000109 } \
110 field = FindInstanceField<Instance ## PrimitiveOrObject ## Read, true>( \
111 field_idx, referrer, self, sizeof(PrimitiveType), &obj); \
112 if (LIKELY(field != nullptr)) { \
Andreas Gampe49fc60e2017-08-24 13:19:59 -0700113 return field->Get ## Kind (obj)Ptr; /* NOLINT */ \
Nicolas Geoffray5b3c6c02017-01-19 14:22:26 +0000114 } \
115 /* Will throw exception by checking with Thread::Current. */ \
116 return 0; \
117 } \
118 \
119 extern "C" int artSet ## Kind ## StaticFromCode(uint32_t field_idx, \
120 SetType new_value, \
121 ArtMethod* referrer, \
122 Thread* self) \
123 REQUIRES_SHARED(Locks::mutator_lock_) { \
124 ScopedQuickEntrypointChecks sqec(self); \
125 ArtField* field = FindFieldFast( \
126 field_idx, referrer, Static ## PrimitiveOrObject ## Write, \
127 sizeof(PrimitiveType)); \
128 if (LIKELY(field != nullptr)) { \
129 field->Set ## Kind <false>(field->GetDeclaringClass(), new_value); \
130 return 0; \
131 } \
132 if (IsObject) { \
133 StackHandleScope<1> hs(self); \
134 HandleWrapper<mirror::Object> h_obj(hs.NewHandleWrapper( \
135 reinterpret_cast<mirror::Object**>(&new_value))); \
136 field = FindFieldFromCode<Static ## PrimitiveOrObject ## Write, true>( \
137 field_idx, referrer, self, sizeof(PrimitiveType)); \
138 } else { \
139 field = FindFieldFromCode<Static ## PrimitiveOrObject ## Write, true>( \
140 field_idx, referrer, self, sizeof(PrimitiveType)); \
141 } \
142 if (LIKELY(field != nullptr)) { \
143 field->Set ## Kind <false>(field->GetDeclaringClass(), new_value); \
144 return 0; \
145 } \
146 return -1; \
147 } \
148 \
149 extern "C" int artSet ## Kind ## InstanceFromCode(uint32_t field_idx, \
150 mirror::Object* obj, \
151 SetType new_value, \
152 ArtMethod* referrer, \
153 Thread* self) \
154 REQUIRES_SHARED(Locks::mutator_lock_) { \
155 ScopedQuickEntrypointChecks sqec(self); \
156 ArtField* field = FindFieldFast( \
157 field_idx, referrer, Instance ## PrimitiveOrObject ## Write, \
158 sizeof(PrimitiveType)); \
159 if (LIKELY(field != nullptr && obj != nullptr)) { \
160 field->Set ## Kind <false>(obj, new_value); \
161 return 0; \
162 } \
163 if (IsObject) { \
164 StackHandleScope<1> hs(self); \
165 HandleWrapper<mirror::Object> h_obj(hs.NewHandleWrapper( \
166 reinterpret_cast<mirror::Object**>(&new_value))); \
167 field = FindInstanceField<Instance ## PrimitiveOrObject ## Write, true>( \
168 field_idx, \
169 referrer, \
170 self, \
171 sizeof(PrimitiveType), \
172 &obj); \
173 } else { \
174 field = FindInstanceField<Instance ## PrimitiveOrObject ## Write, true>( \
175 field_idx, \
176 referrer, \
177 self, \
178 sizeof(PrimitiveType), \
179 &obj); \
180 } \
181 if (LIKELY(field != nullptr)) { \
182 field->Set ## Kind<false>(obj, new_value); \
183 return 0; \
184 } \
185 return -1; \
186 } \
187 \
188 extern "C" RetType artGet ## Kind ## StaticFromCompiledCode( \
189 uint32_t field_idx, \
190 Thread* self) \
191 REQUIRES_SHARED(Locks::mutator_lock_) { \
192 return artGet ## Kind ## StaticFromCode( \
193 field_idx, GetReferrer(self), self); \
194 } \
195 \
196 extern "C" RetType artGet ## Kind ## InstanceFromCompiledCode( \
197 uint32_t field_idx, \
198 mirror::Object* obj, \
199 Thread* self) \
200 REQUIRES_SHARED(Locks::mutator_lock_) { \
201 return artGet ## Kind ## InstanceFromCode( \
202 field_idx, obj, GetReferrer(self), self); \
203 } \
204 \
205 extern "C" int artSet ## Kind ## StaticFromCompiledCode( \
206 uint32_t field_idx, \
207 SetType new_value, \
208 Thread* self) \
209 REQUIRES_SHARED(Locks::mutator_lock_) { \
210 return artSet ## Kind ## StaticFromCode( \
211 field_idx, new_value, GetReferrer(self), self); \
212 } \
213 \
214 extern "C" int artSet ## Kind ## InstanceFromCompiledCode( \
215 uint32_t field_idx, \
216 mirror::Object* obj, \
217 SetType new_value, \
218 Thread* self) \
219 REQUIRES_SHARED(Locks::mutator_lock_) { \
220 return artSet ## Kind ## InstanceFromCode( \
221 field_idx, obj, new_value, GetReferrer(self), self); \
222 }
223
Roland Levillain809f5b12018-01-04 14:05:59 +0000224// Define these functions:
225//
226// artGetByteStaticFromCode
227// artGetByteInstanceFromCode
228// artSetByteStaticFromCode
229// artSetByteInstanceFromCode
230// artGetByteStaticFromCompiledCode
231// artGetByteInstanceFromCompiledCode
232// artSetByteStaticFromCompiledCode
233// artSetByteInstanceFromCompiledCode
234//
Nicolas Geoffray5b3c6c02017-01-19 14:22:26 +0000235ART_GET_FIELD_FROM_CODE(Byte, int8_t, ssize_t, uint32_t, Primitive, false, )
Roland Levillain809f5b12018-01-04 14:05:59 +0000236
237// Define these functions:
238//
239// artGetBooleanStaticFromCode
240// artGetBooleanInstanceFromCode
241// artSetBooleanStaticFromCode
242// artSetBooleanInstanceFromCode
243// artGetBooleanStaticFromCompiledCode
244// artGetBooleanInstanceFromCompiledCode
245// artSetBooleanStaticFromCompiledCode
246// artSetBooleanInstanceFromCompiledCode
247//
Nicolas Geoffray5b3c6c02017-01-19 14:22:26 +0000248ART_GET_FIELD_FROM_CODE(Boolean, int8_t, size_t, uint32_t, Primitive, false, )
Roland Levillain809f5b12018-01-04 14:05:59 +0000249
250// Define these functions:
251//
252// artGetShortStaticFromCode
253// artGetShortInstanceFromCode
254// artSetShortStaticFromCode
255// artSetShortInstanceFromCode
256// artGetShortStaticFromCompiledCode
257// artGetShortInstanceFromCompiledCode
258// artSetShortStaticFromCompiledCode
259// artSetShortInstanceFromCompiledCode
260//
Nicolas Geoffray5b3c6c02017-01-19 14:22:26 +0000261ART_GET_FIELD_FROM_CODE(Short, int16_t, ssize_t, uint16_t, Primitive, false, )
Roland Levillain809f5b12018-01-04 14:05:59 +0000262
263// Define these functions:
264//
265// artGetCharStaticFromCode
266// artGetCharInstanceFromCode
267// artSetCharStaticFromCode
268// artSetCharInstanceFromCode
269// artGetCharStaticFromCompiledCode
270// artGetCharInstanceFromCompiledCode
271// artSetCharStaticFromCompiledCode
272// artSetCharInstanceFromCompiledCode
273//
Nicolas Geoffray5b3c6c02017-01-19 14:22:26 +0000274ART_GET_FIELD_FROM_CODE(Char, int16_t, size_t, uint16_t, Primitive, false, )
Roland Levillain809f5b12018-01-04 14:05:59 +0000275
276// Define these functions:
277//
278// artGet32StaticFromCode
279// artGet32InstanceFromCode
280// artSet32StaticFromCode
281// artSet32InstanceFromCode
282// artGet32StaticFromCompiledCode
283// artGet32InstanceFromCompiledCode
284// artSet32StaticFromCompiledCode
285// artSet32InstanceFromCompiledCode
286//
Nicolas Geoffray5b3c6c02017-01-19 14:22:26 +0000287ART_GET_FIELD_FROM_CODE(32, int32_t, size_t, uint32_t, Primitive, false, )
Roland Levillain809f5b12018-01-04 14:05:59 +0000288
289// Define these functions:
290//
291// artGet64StaticFromCode
292// artGet64InstanceFromCode
293// artSet64StaticFromCode
294// artSet64InstanceFromCode
295// artGet64StaticFromCompiledCode
296// artGet64InstanceFromCompiledCode
297// artSet64StaticFromCompiledCode
298// artSet64InstanceFromCompiledCode
299//
Nicolas Geoffray5b3c6c02017-01-19 14:22:26 +0000300ART_GET_FIELD_FROM_CODE(64, int64_t, uint64_t, uint64_t, Primitive, false, )
Roland Levillain809f5b12018-01-04 14:05:59 +0000301
302// Define these functions:
303//
304// artGetObjStaticFromCode
305// artGetObjInstanceFromCode
306// artSetObjStaticFromCode
307// artSetObjInstanceFromCode
308// artGetObjStaticFromCompiledCode
309// artGetObjInstanceFromCompiledCode
310// artSetObjStaticFromCompiledCode
311// artSetObjInstanceFromCompiledCode
312//
Nicolas Geoffray5b3c6c02017-01-19 14:22:26 +0000313ART_GET_FIELD_FROM_CODE(Obj, mirror::HeapReference<mirror::Object>, mirror::Object*,
314 mirror::Object*, Object, true, .Ptr())
315
Roland Levillain809f5b12018-01-04 14:05:59 +0000316#undef ART_GET_FIELD_FROM_CODE
317
Nicolas Geoffray5b3c6c02017-01-19 14:22:26 +0000318
319// To cut on the number of entrypoints, we have shared entries for
320// byte/boolean and char/short for setting an instance or static field. We just
321// forward those to the unsigned variant.
322extern "C" int artSet8StaticFromCompiledCode(uint32_t field_idx,
323 uint32_t new_value,
324 Thread* self)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700325 REQUIRES_SHARED(Locks::mutator_lock_) {
Nicolas Geoffray5b3c6c02017-01-19 14:22:26 +0000326 return artSetBooleanStaticFromCode(field_idx, new_value, GetReferrer(self), self);
Fred Shih37f05ef2014-07-16 18:38:08 -0700327}
328
Nicolas Geoffray5b3c6c02017-01-19 14:22:26 +0000329extern "C" int artSet16StaticFromCompiledCode(uint32_t field_idx,
330 uint16_t new_value,
Andreas Gampe67409972016-07-19 22:34:53 -0700331 Thread* self)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700332 REQUIRES_SHARED(Locks::mutator_lock_) {
Nicolas Geoffray5b3c6c02017-01-19 14:22:26 +0000333 return artSetCharStaticFromCode(field_idx, new_value, GetReferrer(self), self);
Fred Shih37f05ef2014-07-16 18:38:08 -0700334}
335
Nicolas Geoffray5b3c6c02017-01-19 14:22:26 +0000336extern "C" int artSet8InstanceFromCompiledCode(uint32_t field_idx,
Mathieu Chartierbf369182016-02-04 18:13:32 -0800337 mirror::Object* obj,
Nicolas Geoffray5b3c6c02017-01-19 14:22:26 +0000338 uint8_t new_value,
Mathieu Chartierbf369182016-02-04 18:13:32 -0800339 Thread* self)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700340 REQUIRES_SHARED(Locks::mutator_lock_) {
Nicolas Geoffray5b3c6c02017-01-19 14:22:26 +0000341 return artSetBooleanInstanceFromCode(field_idx, obj, new_value, GetReferrer(self), self);
Fred Shih37f05ef2014-07-16 18:38:08 -0700342}
343
Nicolas Geoffray5b3c6c02017-01-19 14:22:26 +0000344extern "C" int artSet16InstanceFromCompiledCode(uint32_t field_idx,
345 mirror::Object* obj,
346 uint16_t new_value,
347 Thread* self)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700348 REQUIRES_SHARED(Locks::mutator_lock_) {
Nicolas Geoffray5b3c6c02017-01-19 14:22:26 +0000349 return artSetCharInstanceFromCode(field_idx, obj, new_value, GetReferrer(self), self);
Ian Rogers57b86d42012-03-27 16:05:41 -0700350}
351
Mathieu Chartierbf369182016-02-04 18:13:32 -0800352extern "C" int artSet8StaticFromCode(uint32_t field_idx,
353 uint32_t new_value,
354 ArtMethod* referrer,
355 Thread* self)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700356 REQUIRES_SHARED(Locks::mutator_lock_) {
Nicolas Geoffray5b3c6c02017-01-19 14:22:26 +0000357 return artSetBooleanStaticFromCode(field_idx, new_value, referrer, self);
Fred Shih37f05ef2014-07-16 18:38:08 -0700358}
359
Mathieu Chartierbf369182016-02-04 18:13:32 -0800360extern "C" int artSet16StaticFromCode(uint32_t field_idx,
361 uint16_t new_value,
362 ArtMethod* referrer,
363 Thread* self)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700364 REQUIRES_SHARED(Locks::mutator_lock_) {
Nicolas Geoffray5b3c6c02017-01-19 14:22:26 +0000365 return artSetCharStaticFromCode(field_idx, new_value, referrer, self);
Ian Rogers57b86d42012-03-27 16:05:41 -0700366}
367
Mathieu Chartierbf369182016-02-04 18:13:32 -0800368extern "C" int artSet8InstanceFromCode(uint32_t field_idx,
369 mirror::Object* obj,
370 uint8_t new_value,
371 ArtMethod* referrer,
372 Thread* self)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700373 REQUIRES_SHARED(Locks::mutator_lock_) {
Nicolas Geoffray5b3c6c02017-01-19 14:22:26 +0000374 return artSetBooleanInstanceFromCode(field_idx, obj, new_value, referrer, self);
Fred Shih37f05ef2014-07-16 18:38:08 -0700375}
376
Mathieu Chartierbf369182016-02-04 18:13:32 -0800377extern "C" int artSet16InstanceFromCode(uint32_t field_idx,
378 mirror::Object* obj,
379 uint16_t new_value,
380 ArtMethod* referrer,
381 Thread* self)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700382 REQUIRES_SHARED(Locks::mutator_lock_) {
Nicolas Geoffray5b3c6c02017-01-19 14:22:26 +0000383 return artSetCharInstanceFromCode(field_idx, obj, new_value, referrer, self);
Ian Rogers57b86d42012-03-27 16:05:41 -0700384}
385
Roland Levillain7c1559a2015-12-15 10:55:36 +0000386extern "C" mirror::Object* artReadBarrierMark(mirror::Object* obj) {
387 DCHECK(kEmitCompilerReadBarrier);
388 return ReadBarrier::Mark(obj);
389}
390
Man Cao1aee9002015-07-14 22:31:42 -0700391extern "C" mirror::Object* artReadBarrierSlow(mirror::Object* ref ATTRIBUTE_UNUSED,
Roland Levillain0d5a2812015-11-13 10:07:31 +0000392 mirror::Object* obj,
393 uint32_t offset) {
Hans Boehmcc55e1d2017-07-27 15:28:07 -0700394 // Used only in connection with non-volatile loads.
Roland Levillain0d5a2812015-11-13 10:07:31 +0000395 DCHECK(kEmitCompilerReadBarrier);
Man Cao1aee9002015-07-14 22:31:42 -0700396 uint8_t* raw_addr = reinterpret_cast<uint8_t*>(obj) + offset;
397 mirror::HeapReference<mirror::Object>* ref_addr =
Roland Levillain0d5a2812015-11-13 10:07:31 +0000398 reinterpret_cast<mirror::HeapReference<mirror::Object>*>(raw_addr);
399 constexpr ReadBarrierOption kReadBarrierOption =
400 kUseReadBarrier ? kWithReadBarrier : kWithoutReadBarrier;
401 mirror::Object* result =
Hans Boehmcc55e1d2017-07-27 15:28:07 -0700402 ReadBarrier::Barrier<mirror::Object, /* kIsVolatile */ false, kReadBarrierOption>(
403 obj,
404 MemberOffset(offset),
405 ref_addr);
Roland Levillain0d5a2812015-11-13 10:07:31 +0000406 return result;
407}
408
409extern "C" mirror::Object* artReadBarrierForRootSlow(GcRoot<mirror::Object>* root) {
410 DCHECK(kEmitCompilerReadBarrier);
Roland Levillain0d5a2812015-11-13 10:07:31 +0000411 return root->Read();
Man Cao1aee9002015-07-14 22:31:42 -0700412}
413
Ian Rogers57b86d42012-03-27 16:05:41 -0700414} // namespace art