blob: bfe015ffc223a883fa3dba9db83f34f25d9a0017 [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"
David Sehr9e734c72018-01-04 17:56:19 -080023#include "dex/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 -080031// Helper function to do a null check after trying to resolve the field. Not for statics since obj
32// does not exist there. There is a suspend check, object is a double pointer to update the value
33// in the caller in case it moves.
Mathieu Chartierbf369182016-02-04 18:13:32 -080034template<FindFieldType type, bool kAccessCheck>
35ALWAYS_INLINE static inline ArtField* FindInstanceField(uint32_t field_idx,
36 ArtMethod* referrer,
37 Thread* self,
38 size_t size,
39 mirror::Object** obj)
40 REQUIRES(!Roles::uninterruptible_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -070041 REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartierbf369182016-02-04 18:13:32 -080042 StackHandleScope<1> hs(self);
43 HandleWrapper<mirror::Object> h(hs.NewHandleWrapper(obj));
44 ArtField* field = FindFieldFromCode<type, kAccessCheck>(field_idx, referrer, self, size);
Andreas Gampefa4333d2017-02-14 11:10:34 -080045 if (LIKELY(field != nullptr) && UNLIKELY(h == nullptr)) {
David Srbeckyce32c102018-08-31 07:21:07 +010046 ThrowNullPointerExceptionForFieldAccess(field, (type & FindFieldFlags::ReadBit) != 0);
Mathieu Chartierbf369182016-02-04 18:13:32 -080047 return nullptr;
48 }
49 return field;
50}
51
Nicolas Geoffray5b3c6c02017-01-19 14:22:26 +000052static ArtMethod* GetReferrer(Thread* self) REQUIRES_SHARED(Locks::mutator_lock_) {
53 if (kIsDebugBuild) {
54 // stub_test doesn't call this code with a proper frame, so get the outer, and if
55 // it does not have compiled code return it.
Andreas Gampe8228cdf2017-05-30 15:03:54 -070056 ArtMethod* outer = GetCalleeSaveOuterMethod(self, CalleeSaveType::kSaveRefsOnly);
Nicolas Geoffray5b3c6c02017-01-19 14:22:26 +000057 if (outer->GetEntryPointFromQuickCompiledCode() == nullptr) {
58 return outer;
59 }
Fred Shih37f05ef2014-07-16 18:38:08 -070060 }
Andreas Gampe8228cdf2017-05-30 15:03:54 -070061 return GetCalleeSaveMethodCallerAndOuterMethod(self, CalleeSaveType::kSaveRefsOnly).caller;
Fred Shih37f05ef2014-07-16 18:38:08 -070062}
63
Roland Levillain809f5b12018-01-04 14:05:59 +000064// Macro used to define this set of functions:
65//
66// art{Get,Set}<Kind>{Static,Instance}FromCode
67// art{Get,Set}<Kind>{Static,Instance}FromCompiledCode
68//
Nicolas Geoffray5b3c6c02017-01-19 14:22:26 +000069#define ART_GET_FIELD_FROM_CODE(Kind, PrimitiveType, RetType, SetType, \
70 PrimitiveOrObject, IsObject, Ptr) \
71 extern "C" RetType artGet ## Kind ## StaticFromCode(uint32_t field_idx, \
72 ArtMethod* referrer, \
73 Thread* self) \
74 REQUIRES_SHARED(Locks::mutator_lock_) { \
75 ScopedQuickEntrypointChecks sqec(self); \
76 ArtField* field = FindFieldFast( \
77 field_idx, referrer, Static ## PrimitiveOrObject ## Read, \
78 sizeof(PrimitiveType)); \
79 if (LIKELY(field != nullptr)) { \
Andreas Gampe49fc60e2017-08-24 13:19:59 -070080 return field->Get ## Kind (field->GetDeclaringClass())Ptr; /* NOLINT */ \
Nicolas Geoffray5b3c6c02017-01-19 14:22:26 +000081 } \
82 field = FindFieldFromCode<Static ## PrimitiveOrObject ## Read, true>( \
83 field_idx, referrer, self, sizeof(PrimitiveType)); \
84 if (LIKELY(field != nullptr)) { \
Andreas Gampe49fc60e2017-08-24 13:19:59 -070085 return field->Get ## Kind (field->GetDeclaringClass())Ptr; /* NOLINT */ \
Nicolas Geoffray5b3c6c02017-01-19 14:22:26 +000086 } \
87 /* Will throw exception by checking with Thread::Current. */ \
88 return 0; \
89 } \
90 \
91 extern "C" RetType artGet ## Kind ## InstanceFromCode(uint32_t field_idx, \
92 mirror::Object* obj, \
93 ArtMethod* referrer, \
94 Thread* self) \
95 REQUIRES_SHARED(Locks::mutator_lock_) { \
96 ScopedQuickEntrypointChecks sqec(self); \
97 ArtField* field = FindFieldFast( \
98 field_idx, referrer, Instance ## PrimitiveOrObject ## Read, \
99 sizeof(PrimitiveType)); \
100 if (LIKELY(field != nullptr) && obj != nullptr) { \
Andreas Gampe49fc60e2017-08-24 13:19:59 -0700101 return field->Get ## Kind (obj)Ptr; /* NOLINT */ \
Nicolas Geoffray5b3c6c02017-01-19 14:22:26 +0000102 } \
103 field = FindInstanceField<Instance ## PrimitiveOrObject ## Read, true>( \
104 field_idx, referrer, self, sizeof(PrimitiveType), &obj); \
105 if (LIKELY(field != nullptr)) { \
Andreas Gampe49fc60e2017-08-24 13:19:59 -0700106 return field->Get ## Kind (obj)Ptr; /* NOLINT */ \
Nicolas Geoffray5b3c6c02017-01-19 14:22:26 +0000107 } \
108 /* Will throw exception by checking with Thread::Current. */ \
109 return 0; \
110 } \
111 \
112 extern "C" int artSet ## Kind ## StaticFromCode(uint32_t field_idx, \
113 SetType new_value, \
114 ArtMethod* referrer, \
115 Thread* self) \
116 REQUIRES_SHARED(Locks::mutator_lock_) { \
117 ScopedQuickEntrypointChecks sqec(self); \
118 ArtField* field = FindFieldFast( \
119 field_idx, referrer, Static ## PrimitiveOrObject ## Write, \
120 sizeof(PrimitiveType)); \
Nicolas Geoffray396198b2020-06-16 12:02:45 +0100121 if (UNLIKELY(field == nullptr)) { \
122 if (IsObject) { \
123 StackHandleScope<1> hs(self); \
124 HandleWrapper<mirror::Object> h_obj(hs.NewHandleWrapper( \
125 reinterpret_cast<mirror::Object**>(&new_value))); \
126 field = FindFieldFromCode<Static ## PrimitiveOrObject ## Write, true>( \
127 field_idx, referrer, self, sizeof(PrimitiveType)); \
128 } else { \
129 field = FindFieldFromCode<Static ## PrimitiveOrObject ## Write, true>( \
130 field_idx, referrer, self, sizeof(PrimitiveType)); \
131 } \
132 if (UNLIKELY(field == nullptr)) { \
133 return -1; \
134 } \
Nicolas Geoffray5b3c6c02017-01-19 14:22:26 +0000135 } \
Nicolas Geoffray396198b2020-06-16 12:02:45 +0100136 if (!referrer->SkipAccessChecks() && IsObject && new_value != 0) { \
137 StackArtFieldHandleScope<1> rhs(self); \
138 ReflectiveHandle<ArtField> field_handle(rhs.NewHandle(field)); \
139 if (field->ResolveType().IsNull()) { \
140 self->AssertPendingException(); \
141 return -1; \
142 } \
143 field = field_handle.Get(); \
Nicolas Geoffray5b3c6c02017-01-19 14:22:26 +0000144 } \
Nicolas Geoffray396198b2020-06-16 12:02:45 +0100145 field->Set ## Kind <false>(field->GetDeclaringClass(), new_value); \
146 return 0; \
Nicolas Geoffray5b3c6c02017-01-19 14:22:26 +0000147 } \
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)); \
Nicolas Geoffray396198b2020-06-16 12:02:45 +0100159 if (UNLIKELY(field == nullptr || obj == nullptr)) { \
160 if (IsObject) { \
161 StackHandleScope<1> hs(self); \
162 HandleWrapper<mirror::Object> h_obj(hs.NewHandleWrapper( \
163 reinterpret_cast<mirror::Object**>(&new_value))); \
164 field = \
165 FindInstanceField<Instance ## PrimitiveOrObject ## Write, true>( \
166 field_idx, \
167 referrer, \
168 self, \
169 sizeof(PrimitiveType), \
170 &obj); \
171 } else { \
172 field = \
173 FindInstanceField<Instance ## PrimitiveOrObject ## Write, true>( \
174 field_idx, \
175 referrer, \
176 self, \
177 sizeof(PrimitiveType), \
178 &obj); \
179 } \
180 if (UNLIKELY(field == nullptr)) { \
181 return -1; \
182 } \
Nicolas Geoffray5b3c6c02017-01-19 14:22:26 +0000183 } \
Nicolas Geoffray396198b2020-06-16 12:02:45 +0100184 if (!referrer->SkipAccessChecks() && IsObject && new_value != 0) { \
185 StackArtFieldHandleScope<1> rhs(self); \
186 ReflectiveHandle<ArtField> field_handle(rhs.NewHandle(field)); \
187 if (field->ResolveType().IsNull()) { \
188 self->AssertPendingException(); \
189 return -1; \
190 } \
191 field = field_handle.Get(); \
Nicolas Geoffray5b3c6c02017-01-19 14:22:26 +0000192 } \
Nicolas Geoffray396198b2020-06-16 12:02:45 +0100193 field->Set ## Kind<false>(obj, new_value); \
194 return 0; \
Nicolas Geoffray5b3c6c02017-01-19 14:22:26 +0000195 } \
196 \
197 extern "C" RetType artGet ## Kind ## StaticFromCompiledCode( \
198 uint32_t field_idx, \
199 Thread* self) \
200 REQUIRES_SHARED(Locks::mutator_lock_) { \
201 return artGet ## Kind ## StaticFromCode( \
202 field_idx, GetReferrer(self), self); \
203 } \
204 \
205 extern "C" RetType artGet ## Kind ## InstanceFromCompiledCode( \
206 uint32_t field_idx, \
207 mirror::Object* obj, \
208 Thread* self) \
209 REQUIRES_SHARED(Locks::mutator_lock_) { \
210 return artGet ## Kind ## InstanceFromCode( \
211 field_idx, obj, GetReferrer(self), self); \
212 } \
213 \
214 extern "C" int artSet ## Kind ## StaticFromCompiledCode( \
215 uint32_t field_idx, \
216 SetType new_value, \
217 Thread* self) \
218 REQUIRES_SHARED(Locks::mutator_lock_) { \
219 return artSet ## Kind ## StaticFromCode( \
220 field_idx, new_value, GetReferrer(self), self); \
221 } \
222 \
223 extern "C" int artSet ## Kind ## InstanceFromCompiledCode( \
224 uint32_t field_idx, \
225 mirror::Object* obj, \
226 SetType new_value, \
227 Thread* self) \
228 REQUIRES_SHARED(Locks::mutator_lock_) { \
229 return artSet ## Kind ## InstanceFromCode( \
230 field_idx, obj, new_value, GetReferrer(self), self); \
231 }
232
Roland Levillain809f5b12018-01-04 14:05:59 +0000233// Define these functions:
234//
235// artGetByteStaticFromCode
236// artGetByteInstanceFromCode
237// artSetByteStaticFromCode
238// artSetByteInstanceFromCode
239// artGetByteStaticFromCompiledCode
240// artGetByteInstanceFromCompiledCode
241// artSetByteStaticFromCompiledCode
242// artSetByteInstanceFromCompiledCode
243//
Nicolas Geoffray5b3c6c02017-01-19 14:22:26 +0000244ART_GET_FIELD_FROM_CODE(Byte, int8_t, ssize_t, uint32_t, Primitive, false, )
Roland Levillain809f5b12018-01-04 14:05:59 +0000245
246// Define these functions:
247//
248// artGetBooleanStaticFromCode
249// artGetBooleanInstanceFromCode
250// artSetBooleanStaticFromCode
251// artSetBooleanInstanceFromCode
252// artGetBooleanStaticFromCompiledCode
253// artGetBooleanInstanceFromCompiledCode
254// artSetBooleanStaticFromCompiledCode
255// artSetBooleanInstanceFromCompiledCode
256//
Nicolas Geoffray5b3c6c02017-01-19 14:22:26 +0000257ART_GET_FIELD_FROM_CODE(Boolean, int8_t, size_t, uint32_t, Primitive, false, )
Roland Levillain809f5b12018-01-04 14:05:59 +0000258
259// Define these functions:
260//
261// artGetShortStaticFromCode
262// artGetShortInstanceFromCode
263// artSetShortStaticFromCode
264// artSetShortInstanceFromCode
265// artGetShortStaticFromCompiledCode
266// artGetShortInstanceFromCompiledCode
267// artSetShortStaticFromCompiledCode
268// artSetShortInstanceFromCompiledCode
269//
Nicolas Geoffray5b3c6c02017-01-19 14:22:26 +0000270ART_GET_FIELD_FROM_CODE(Short, int16_t, ssize_t, uint16_t, Primitive, false, )
Roland Levillain809f5b12018-01-04 14:05:59 +0000271
272// Define these functions:
273//
274// artGetCharStaticFromCode
275// artGetCharInstanceFromCode
276// artSetCharStaticFromCode
277// artSetCharInstanceFromCode
278// artGetCharStaticFromCompiledCode
279// artGetCharInstanceFromCompiledCode
280// artSetCharStaticFromCompiledCode
281// artSetCharInstanceFromCompiledCode
282//
Nicolas Geoffray5b3c6c02017-01-19 14:22:26 +0000283ART_GET_FIELD_FROM_CODE(Char, int16_t, size_t, uint16_t, Primitive, false, )
Roland Levillain809f5b12018-01-04 14:05:59 +0000284
285// Define these functions:
286//
287// artGet32StaticFromCode
288// artGet32InstanceFromCode
289// artSet32StaticFromCode
290// artSet32InstanceFromCode
291// artGet32StaticFromCompiledCode
292// artGet32InstanceFromCompiledCode
293// artSet32StaticFromCompiledCode
294// artSet32InstanceFromCompiledCode
295//
Nicolas Geoffray5b3c6c02017-01-19 14:22:26 +0000296ART_GET_FIELD_FROM_CODE(32, int32_t, size_t, uint32_t, Primitive, false, )
Roland Levillain809f5b12018-01-04 14:05:59 +0000297
298// Define these functions:
299//
300// artGet64StaticFromCode
301// artGet64InstanceFromCode
302// artSet64StaticFromCode
303// artSet64InstanceFromCode
304// artGet64StaticFromCompiledCode
305// artGet64InstanceFromCompiledCode
306// artSet64StaticFromCompiledCode
307// artSet64InstanceFromCompiledCode
308//
Nicolas Geoffray5b3c6c02017-01-19 14:22:26 +0000309ART_GET_FIELD_FROM_CODE(64, int64_t, uint64_t, uint64_t, Primitive, false, )
Roland Levillain809f5b12018-01-04 14:05:59 +0000310
311// Define these functions:
312//
313// artGetObjStaticFromCode
314// artGetObjInstanceFromCode
315// artSetObjStaticFromCode
316// artSetObjInstanceFromCode
317// artGetObjStaticFromCompiledCode
318// artGetObjInstanceFromCompiledCode
319// artSetObjStaticFromCompiledCode
320// artSetObjInstanceFromCompiledCode
321//
Nicolas Geoffray5b3c6c02017-01-19 14:22:26 +0000322ART_GET_FIELD_FROM_CODE(Obj, mirror::HeapReference<mirror::Object>, mirror::Object*,
323 mirror::Object*, Object, true, .Ptr())
324
Roland Levillain809f5b12018-01-04 14:05:59 +0000325#undef ART_GET_FIELD_FROM_CODE
326
Nicolas Geoffray5b3c6c02017-01-19 14:22:26 +0000327
328// To cut on the number of entrypoints, we have shared entries for
329// byte/boolean and char/short for setting an instance or static field. We just
330// forward those to the unsigned variant.
331extern "C" int artSet8StaticFromCompiledCode(uint32_t field_idx,
332 uint32_t new_value,
333 Thread* self)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700334 REQUIRES_SHARED(Locks::mutator_lock_) {
Nicolas Geoffray5b3c6c02017-01-19 14:22:26 +0000335 return artSetBooleanStaticFromCode(field_idx, new_value, GetReferrer(self), self);
Fred Shih37f05ef2014-07-16 18:38:08 -0700336}
337
Nicolas Geoffray5b3c6c02017-01-19 14:22:26 +0000338extern "C" int artSet16StaticFromCompiledCode(uint32_t field_idx,
339 uint16_t new_value,
Andreas Gampe67409972016-07-19 22:34:53 -0700340 Thread* self)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700341 REQUIRES_SHARED(Locks::mutator_lock_) {
Nicolas Geoffray5b3c6c02017-01-19 14:22:26 +0000342 return artSetCharStaticFromCode(field_idx, new_value, GetReferrer(self), self);
Fred Shih37f05ef2014-07-16 18:38:08 -0700343}
344
Nicolas Geoffray5b3c6c02017-01-19 14:22:26 +0000345extern "C" int artSet8InstanceFromCompiledCode(uint32_t field_idx,
Mathieu Chartierbf369182016-02-04 18:13:32 -0800346 mirror::Object* obj,
Nicolas Geoffray5b3c6c02017-01-19 14:22:26 +0000347 uint8_t new_value,
Mathieu Chartierbf369182016-02-04 18:13:32 -0800348 Thread* self)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700349 REQUIRES_SHARED(Locks::mutator_lock_) {
Nicolas Geoffray5b3c6c02017-01-19 14:22:26 +0000350 return artSetBooleanInstanceFromCode(field_idx, obj, new_value, GetReferrer(self), self);
Fred Shih37f05ef2014-07-16 18:38:08 -0700351}
352
Nicolas Geoffray5b3c6c02017-01-19 14:22:26 +0000353extern "C" int artSet16InstanceFromCompiledCode(uint32_t field_idx,
354 mirror::Object* obj,
355 uint16_t new_value,
356 Thread* self)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700357 REQUIRES_SHARED(Locks::mutator_lock_) {
Nicolas Geoffray5b3c6c02017-01-19 14:22:26 +0000358 return artSetCharInstanceFromCode(field_idx, obj, new_value, GetReferrer(self), self);
Ian Rogers57b86d42012-03-27 16:05:41 -0700359}
360
Mathieu Chartierbf369182016-02-04 18:13:32 -0800361extern "C" int artSet8StaticFromCode(uint32_t field_idx,
362 uint32_t new_value,
363 ArtMethod* referrer,
364 Thread* self)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700365 REQUIRES_SHARED(Locks::mutator_lock_) {
Nicolas Geoffray5b3c6c02017-01-19 14:22:26 +0000366 return artSetBooleanStaticFromCode(field_idx, new_value, referrer, self);
Fred Shih37f05ef2014-07-16 18:38:08 -0700367}
368
Mathieu Chartierbf369182016-02-04 18:13:32 -0800369extern "C" int artSet16StaticFromCode(uint32_t field_idx,
370 uint16_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 artSetCharStaticFromCode(field_idx, new_value, referrer, self);
Ian Rogers57b86d42012-03-27 16:05:41 -0700375}
376
Mathieu Chartierbf369182016-02-04 18:13:32 -0800377extern "C" int artSet8InstanceFromCode(uint32_t field_idx,
378 mirror::Object* obj,
379 uint8_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 artSetBooleanInstanceFromCode(field_idx, obj, new_value, referrer, self);
Fred Shih37f05ef2014-07-16 18:38:08 -0700384}
385
Mathieu Chartierbf369182016-02-04 18:13:32 -0800386extern "C" int artSet16InstanceFromCode(uint32_t field_idx,
387 mirror::Object* obj,
388 uint16_t new_value,
389 ArtMethod* referrer,
390 Thread* self)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700391 REQUIRES_SHARED(Locks::mutator_lock_) {
Nicolas Geoffray5b3c6c02017-01-19 14:22:26 +0000392 return artSetCharInstanceFromCode(field_idx, obj, new_value, referrer, self);
Ian Rogers57b86d42012-03-27 16:05:41 -0700393}
394
Roland Levillain7c1559a2015-12-15 10:55:36 +0000395extern "C" mirror::Object* artReadBarrierMark(mirror::Object* obj) {
396 DCHECK(kEmitCompilerReadBarrier);
397 return ReadBarrier::Mark(obj);
398}
399
Man Cao1aee9002015-07-14 22:31:42 -0700400extern "C" mirror::Object* artReadBarrierSlow(mirror::Object* ref ATTRIBUTE_UNUSED,
Roland Levillain0d5a2812015-11-13 10:07:31 +0000401 mirror::Object* obj,
402 uint32_t offset) {
Hans Boehmcc55e1d2017-07-27 15:28:07 -0700403 // Used only in connection with non-volatile loads.
Roland Levillain0d5a2812015-11-13 10:07:31 +0000404 DCHECK(kEmitCompilerReadBarrier);
Man Cao1aee9002015-07-14 22:31:42 -0700405 uint8_t* raw_addr = reinterpret_cast<uint8_t*>(obj) + offset;
406 mirror::HeapReference<mirror::Object>* ref_addr =
Roland Levillain0d5a2812015-11-13 10:07:31 +0000407 reinterpret_cast<mirror::HeapReference<mirror::Object>*>(raw_addr);
408 constexpr ReadBarrierOption kReadBarrierOption =
409 kUseReadBarrier ? kWithReadBarrier : kWithoutReadBarrier;
410 mirror::Object* result =
Andreas Gampe98ea9d92018-10-19 14:06:15 -0700411 ReadBarrier::Barrier<mirror::Object, /* kIsVolatile= */ false, kReadBarrierOption>(
Hans Boehmcc55e1d2017-07-27 15:28:07 -0700412 obj,
413 MemberOffset(offset),
414 ref_addr);
Roland Levillain0d5a2812015-11-13 10:07:31 +0000415 return result;
416}
417
418extern "C" mirror::Object* artReadBarrierForRootSlow(GcRoot<mirror::Object>* root) {
419 DCHECK(kEmitCompilerReadBarrier);
Roland Levillain0d5a2812015-11-13 10:07:31 +0000420 return root->Read();
Man Cao1aee9002015-07-14 22:31:42 -0700421}
422
Ian Rogers57b86d42012-03-27 16:05:41 -0700423} // namespace art