• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1  /*
2   * Copyright (C) 2011 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  
17  #ifndef ART_RUNTIME_MIRROR_OBJECT_INL_H_
18  #define ART_RUNTIME_MIRROR_OBJECT_INL_H_
19  
20  #include "object.h"
21  
22  #include "array-inl.h"
23  #include "art_field.h"
24  #include "art_method.h"
25  #include "base/atomic.h"
26  #include "class-inl.h"
27  #include "class_flags.h"
28  #include "class_linker.h"
29  #include "dex_cache.h"
30  #include "heap_poisoning.h"
31  #include "lock_word-inl.h"
32  #include "monitor.h"
33  #include "obj_ptr-inl.h"
34  #include "object-readbarrier-inl.h"
35  #include "object_array-inl.h"
36  #include "object_reference-inl.h"
37  #include "read_barrier-inl.h"
38  #include "reference.h"
39  #include "runtime.h"
40  #include "string.h"
41  #include "throwable.h"
42  #include "write_barrier-inl.h"
43  
44  namespace art {
45  namespace mirror {
46  
ClassSize(PointerSize pointer_size)47  inline uint32_t Object::ClassSize(PointerSize pointer_size) {
48    uint32_t vtable_entries = kVTableLength;
49    return Class::ComputeClassSize(true, vtable_entries, 0, 0, 0, 0, 0, pointer_size);
50  }
51  
52  template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
GetClass()53  inline Class* Object::GetClass() {
54    return GetFieldObject<Class, kVerifyFlags, kReadBarrierOption>(ClassOffset());
55  }
56  
57  template<VerifyObjectFlags kVerifyFlags>
SetClass(ObjPtr<Class> new_klass)58  inline void Object::SetClass(ObjPtr<Class> new_klass) {
59    // new_klass may be null prior to class linker initialization.
60    // We don't mark the card as this occurs as part of object allocation. Not all objects have
61    // backing cards, such as large objects.
62    // We use non transactional version since we can't undo this write. We also disable checking as
63    // we may run in transaction mode here.
64    SetFieldObjectWithoutWriteBarrier<false, false, RemoveThisFlags(kVerifyFlags)>(ClassOffset(),
65                                                                                   new_klass);
66  }
67  
68  template<VerifyObjectFlags kVerifyFlags>
SetLockWord(LockWord new_val,bool as_volatile)69  inline void Object::SetLockWord(LockWord new_val, bool as_volatile) {
70    // Force use of non-transactional mode and do not check.
71    if (as_volatile) {
72      SetField32Volatile<false, false, kVerifyFlags>(MonitorOffset(), new_val.GetValue());
73    } else {
74      SetField32<false, false, kVerifyFlags>(MonitorOffset(), new_val.GetValue());
75    }
76  }
77  
GetLockOwnerThreadId()78  inline uint32_t Object::GetLockOwnerThreadId() {
79    return Monitor::GetLockOwnerThreadId(this);
80  }
81  
MonitorEnter(Thread * self)82  inline ObjPtr<mirror::Object> Object::MonitorEnter(Thread* self) {
83    return Monitor::MonitorEnter(self, this, /*trylock=*/false);
84  }
85  
MonitorTryEnter(Thread * self)86  inline ObjPtr<mirror::Object> Object::MonitorTryEnter(Thread* self) {
87    return Monitor::MonitorEnter(self, this, /*trylock=*/true);
88  }
89  
MonitorExit(Thread * self)90  inline bool Object::MonitorExit(Thread* self) {
91    return Monitor::MonitorExit(self, this);
92  }
93  
Notify(Thread * self)94  inline void Object::Notify(Thread* self) {
95    Monitor::Notify(self, this);
96  }
97  
NotifyAll(Thread * self)98  inline void Object::NotifyAll(Thread* self) {
99    Monitor::NotifyAll(self, this);
100  }
101  
Wait(Thread * self,int64_t ms,int32_t ns)102  inline void Object::Wait(Thread* self, int64_t ms, int32_t ns) {
103    Monitor::Wait(self, this, ms, ns, true, ThreadState::kTimedWaiting);
104  }
105  
GetMarkBit()106  inline uint32_t Object::GetMarkBit() {
107    CHECK(gUseReadBarrier);
108    return GetLockWord(false).MarkBitState();
109  }
110  
SetReadBarrierState(uint32_t rb_state)111  inline void Object::SetReadBarrierState(uint32_t rb_state) {
112    CHECK(kUseBakerReadBarrier);
113    DCHECK(ReadBarrier::IsValidReadBarrierState(rb_state)) << rb_state;
114    LockWord lw = GetLockWord(false);
115    lw.SetReadBarrierState(rb_state);
116    SetLockWord(lw, false);
117  }
118  
AssertReadBarrierState()119  inline void Object::AssertReadBarrierState() const {
120    CHECK(kUseBakerReadBarrier);
121    Object* obj = const_cast<Object*>(this);
122    DCHECK_EQ(obj->GetReadBarrierState(), ReadBarrier::NonGrayState())
123        << "Bad Baker pointer: obj=" << obj << " rb_state" << obj->GetReadBarrierState();
124  }
125  
126  template<VerifyObjectFlags kVerifyFlags>
VerifierInstanceOf(ObjPtr<Class> klass)127  inline bool Object::VerifierInstanceOf(ObjPtr<Class> klass) {
128    DCHECK(klass != nullptr);
129    DCHECK(GetClass<kVerifyFlags>() != nullptr);
130    return klass->IsInterface() || InstanceOf(klass);
131  }
132  
133  template<VerifyObjectFlags kVerifyFlags>
InstanceOf(ObjPtr<Class> klass)134  inline bool Object::InstanceOf(ObjPtr<Class> klass) {
135    DCHECK(klass != nullptr);
136    DCHECK(GetClass<kVerifyNone>() != nullptr) << "this=" << this;
137    return klass->IsAssignableFrom(GetClass<kVerifyFlags>());
138  }
139  
140  template<VerifyObjectFlags kVerifyFlags>
IsClass()141  inline bool Object::IsClass() {
142    // OK to look at from-space copies since java.lang.Class.class is non-moveable
143    // (even when running without boot image, see ClassLinker::InitWithoutImage())
144    // and we're reading constant references for comparison only. See ReadBarrierOption.
145    ObjPtr<Class> klass = GetClass<kVerifyFlags, kWithoutReadBarrier>();
146    ObjPtr<Class> java_lang_Class = klass->GetClass<kVerifyFlags, kWithoutReadBarrier>();
147    return klass == java_lang_Class;
148  }
149  
150  template<VerifyObjectFlags kVerifyFlags>
AsClass()151  inline ObjPtr<Class> Object::AsClass() {
152    DCHECK((IsClass<kVerifyFlags>()));
153    return ObjPtr<Class>::DownCast(this);
154  }
155  
156  template<VerifyObjectFlags kVerifyFlags>
IsObjectArray()157  inline bool Object::IsObjectArray() {
158    // We do not need a read barrier here as the primitive type is constant,
159    // both from-space and to-space component type classes shall yield the same result.
160    constexpr VerifyObjectFlags kNewFlags = RemoveThisFlags(kVerifyFlags);
161    return IsArrayInstance<kVerifyFlags>() &&
162        !GetClass<kNewFlags, kWithoutReadBarrier>()->
163            template GetComponentType<kNewFlags, kWithoutReadBarrier>()->IsPrimitive();
164  }
165  
166  template<class T, VerifyObjectFlags kVerifyFlags>
AsObjectArray()167  inline ObjPtr<ObjectArray<T>> Object::AsObjectArray() {
168    DCHECK((IsObjectArray<kVerifyFlags>()));
169    return ObjPtr<ObjectArray<T>>::DownCast(this);
170  }
171  
172  template<VerifyObjectFlags kVerifyFlags>
IsArrayInstance()173  inline bool Object::IsArrayInstance() {
174    // We do not need a read barrier here, both from-space and to-space version of the class
175    // shall return the same result from IsArrayClass().
176    return GetClass<kVerifyFlags, kWithoutReadBarrier>()->template IsArrayClass<kVerifyFlags>();
177  }
178  
179  template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
IsReferenceInstance()180  inline bool Object::IsReferenceInstance() {
181    return GetClass<kVerifyFlags, kReadBarrierOption>()->IsTypeOfReferenceClass();
182  }
183  
184  template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
AsReference()185  inline ObjPtr<Reference> Object::AsReference() {
186    DCHECK((IsReferenceInstance<kVerifyFlags, kReadBarrierOption>()));
187    return ObjPtr<Reference>::DownCast(this);
188  }
189  
190  template<VerifyObjectFlags kVerifyFlags>
AsArray()191  inline ObjPtr<Array> Object::AsArray() {
192    DCHECK((IsArrayInstance<kVerifyFlags>()));
193    return ObjPtr<Array>::DownCast(this);
194  }
195  
196  template<VerifyObjectFlags kVerifyFlags, Primitive::Type kType>
IsSpecificPrimitiveArray()197  ALWAYS_INLINE bool Object::IsSpecificPrimitiveArray() {
198    // We do not need a read barrier here as the primitive type is constant, both from-space
199    // and to-space component type classes shall yield the same result. See ReadBarrierOption.
200    const ObjPtr<Class> klass = GetClass<kVerifyFlags, kWithoutReadBarrier>();
201    constexpr VerifyObjectFlags kNewFlags = RemoveThisFlags(kVerifyFlags);
202    const ObjPtr<Class> component_type = klass->GetComponentType<kNewFlags, kWithoutReadBarrier>();
203    return component_type != nullptr &&
204           component_type->GetPrimitiveType<kNewFlags>() == kType;
205  }
206  
207  template<VerifyObjectFlags kVerifyFlags>
IsBooleanArray()208  inline bool Object::IsBooleanArray() {
209    return IsSpecificPrimitiveArray<kVerifyFlags, Primitive::kPrimBoolean>();
210  }
211  
212  template<VerifyObjectFlags kVerifyFlags>
AsBooleanArray()213  inline ObjPtr<BooleanArray> Object::AsBooleanArray() {
214    DCHECK(IsBooleanArray<kVerifyFlags>());
215    return ObjPtr<BooleanArray>::DownCast(this);
216  }
217  
218  template<VerifyObjectFlags kVerifyFlags>
IsByteArray()219  inline bool Object::IsByteArray() {
220    return IsSpecificPrimitiveArray<kVerifyFlags, Primitive::kPrimByte>();
221  }
222  
223  template<VerifyObjectFlags kVerifyFlags>
AsByteArray()224  inline ObjPtr<ByteArray> Object::AsByteArray() {
225    DCHECK(IsByteArray<kVerifyFlags>());
226    return ObjPtr<ByteArray>::DownCast(this);
227  }
228  
229  template<VerifyObjectFlags kVerifyFlags>
IsCharArray()230  inline bool Object::IsCharArray() {
231    return IsSpecificPrimitiveArray<kVerifyFlags, Primitive::kPrimChar>();
232  }
233  
234  template<VerifyObjectFlags kVerifyFlags>
AsCharArray()235  inline ObjPtr<CharArray> Object::AsCharArray() {
236    DCHECK(IsCharArray<kVerifyFlags>());
237    return ObjPtr<CharArray>::DownCast(this);
238  }
239  
240  template<VerifyObjectFlags kVerifyFlags>
IsShortArray()241  inline bool Object::IsShortArray() {
242    return IsSpecificPrimitiveArray<kVerifyFlags, Primitive::kPrimShort>();
243  }
244  
245  template<VerifyObjectFlags kVerifyFlags>
AsShortArray()246  inline ObjPtr<ShortArray> Object::AsShortArray() {
247    DCHECK(IsShortArray<kVerifyFlags>());
248    return ObjPtr<ShortArray>::DownCast(this);
249  }
250  
251  template<VerifyObjectFlags kVerifyFlags>
IsIntArray()252  inline bool Object::IsIntArray() {
253    return IsSpecificPrimitiveArray<kVerifyFlags, Primitive::kPrimInt>();
254  }
255  
256  template<VerifyObjectFlags kVerifyFlags>
AsIntArrayUnchecked()257  inline ObjPtr<IntArray> Object::AsIntArrayUnchecked() {
258    return ObjPtr<IntArray>::DownCast(this);
259  }
260  template<VerifyObjectFlags kVerifyFlags>
AsIntArray()261  inline ObjPtr<IntArray> Object::AsIntArray() {
262    DCHECK((IsIntArray<kVerifyFlags>()));
263    return AsIntArrayUnchecked<kVerifyFlags>();
264  }
265  
266  template<VerifyObjectFlags kVerifyFlags>
IsLongArray()267  inline bool Object::IsLongArray() {
268    return IsSpecificPrimitiveArray<kVerifyFlags, Primitive::kPrimLong>();
269  }
270  
271  template<VerifyObjectFlags kVerifyFlags>
AsLongArrayUnchecked()272  inline ObjPtr<LongArray> Object::AsLongArrayUnchecked() {
273    return ObjPtr<LongArray>::DownCast(this);
274  }
275  template<VerifyObjectFlags kVerifyFlags>
AsLongArray()276  inline ObjPtr<LongArray> Object::AsLongArray() {
277    DCHECK((IsLongArray<kVerifyFlags>()));
278    return AsLongArrayUnchecked<kVerifyFlags>();
279  }
280  
281  template<VerifyObjectFlags kVerifyFlags>
IsFloatArray()282  inline bool Object::IsFloatArray() {
283    return IsSpecificPrimitiveArray<kVerifyFlags, Primitive::kPrimFloat>();
284  }
285  
286  template<VerifyObjectFlags kVerifyFlags>
AsFloatArray()287  inline ObjPtr<FloatArray> Object::AsFloatArray() {
288    DCHECK(IsFloatArray<kVerifyFlags>());
289    return ObjPtr<FloatArray>::DownCast(this);
290  }
291  
292  template<VerifyObjectFlags kVerifyFlags>
IsDoubleArray()293  inline bool Object::IsDoubleArray() {
294    return IsSpecificPrimitiveArray<kVerifyFlags, Primitive::kPrimDouble>();
295  }
296  
297  template<VerifyObjectFlags kVerifyFlags>
AsDoubleArray()298  inline ObjPtr<DoubleArray> Object::AsDoubleArray() {
299    DCHECK(IsDoubleArray<kVerifyFlags>());
300    return ObjPtr<DoubleArray>::DownCast(this);
301  }
302  
303  template<VerifyObjectFlags kVerifyFlags>
IsString()304  inline bool Object::IsString() {
305    // No read barrier is needed for reading a constant primitive field through
306    // constant reference field. See ReadBarrierOption.
307    return GetClass<kVerifyFlags, kWithoutReadBarrier>()->IsStringClass();
308  }
309  
310  template<VerifyObjectFlags kVerifyFlags>
AsString()311  inline ObjPtr<String> Object::AsString() {
312    DCHECK((IsString<kVerifyFlags>()));
313    return ObjPtr<String>::DownCast(this);
314  }
315  
316  template<VerifyObjectFlags kVerifyFlags>
AsThrowable()317  inline ObjPtr<Throwable> Object::AsThrowable() {
318    DCHECK(GetClass<kVerifyFlags>()->IsThrowableClass());
319    return ObjPtr<Throwable>::DownCast(this);
320  }
321  
322  template<VerifyObjectFlags kVerifyFlags>
IsWeakReferenceInstance()323  inline bool Object::IsWeakReferenceInstance() {
324    return GetClass<kVerifyFlags>()->IsWeakReferenceClass();
325  }
326  
327  template<VerifyObjectFlags kVerifyFlags>
IsSoftReferenceInstance()328  inline bool Object::IsSoftReferenceInstance() {
329    return GetClass<kVerifyFlags>()->IsSoftReferenceClass();
330  }
331  
332  template<VerifyObjectFlags kVerifyFlags>
IsFinalizerReferenceInstance()333  inline bool Object::IsFinalizerReferenceInstance() {
334    return GetClass<kVerifyFlags>()->IsFinalizerReferenceClass();
335  }
336  
337  template<VerifyObjectFlags kVerifyFlags>
AsFinalizerReference()338  inline ObjPtr<FinalizerReference> Object::AsFinalizerReference() {
339    DCHECK(IsFinalizerReferenceInstance<kVerifyFlags>());
340    return ObjPtr<FinalizerReference>::DownCast(this);
341  }
342  
343  template<VerifyObjectFlags kVerifyFlags>
IsPhantomReferenceInstance()344  inline bool Object::IsPhantomReferenceInstance() {
345    return GetClass<kVerifyFlags>()->IsPhantomReferenceClass();
346  }
347  
348  template<VerifyObjectFlags kVerifyFlags>
SizeOf()349  inline size_t Object::SizeOf() {
350    // Read barrier is never required for SizeOf since objects sizes are constant. Reading from-space
351    // values is OK because of that.
352    size_t result;
353    constexpr VerifyObjectFlags kNewFlags = RemoveThisFlags(kVerifyFlags);
354    if (IsArrayInstance<kVerifyFlags>()) {
355      result = AsArray<kNewFlags>()->template SizeOf<kNewFlags>();
356    } else if (IsClass<kNewFlags>()) {
357      result = AsClass<kNewFlags>()->template SizeOf<kNewFlags>();
358    } else if (IsString<kNewFlags>()) {
359      result = AsString<kNewFlags>()->template SizeOf<kNewFlags>();
360    } else {
361      result = GetClass<kNewFlags, kWithoutReadBarrier>()->template GetObjectSize<kNewFlags>();
362    }
363    DCHECK_GE(result, sizeof(Object)) << " class="
364        // Note: Class::PrettyClass() is reading constant reference fields to get to constant
365        // primitive fields and safely avoids read barriers, so it is safe to call on a Class
366        // reference read without read barrier from a constant reference field.
367        // See ReadBarrierOption. And, for correctness, we actually have to avoid the read
368        // barrier here if Object::SizeOf() is called on a from-space reference.
369        << GetClass<kNewFlags, kWithoutReadBarrier>()->PrettyClass();
370    return result;
371  }
372  
373  template<VerifyObjectFlags kVerifyFlags, bool kIsVolatile>
GetFieldByte(MemberOffset field_offset)374  inline int8_t Object::GetFieldByte(MemberOffset field_offset) {
375    Verify<kVerifyFlags>();
376    return GetFieldPrimitive<int8_t, kIsVolatile>(field_offset);
377  }
378  
379  template<VerifyObjectFlags kVerifyFlags>
GetFieldBooleanVolatile(MemberOffset field_offset)380  inline uint8_t Object::GetFieldBooleanVolatile(MemberOffset field_offset) {
381    return GetFieldBoolean<kVerifyFlags, true>(field_offset);
382  }
383  
384  template<VerifyObjectFlags kVerifyFlags>
GetFieldByteVolatile(MemberOffset field_offset)385  inline int8_t Object::GetFieldByteVolatile(MemberOffset field_offset) {
386    return GetFieldByte<kVerifyFlags, true>(field_offset);
387  }
388  
389  template<bool kTransactionActive,
390           bool kCheckTransaction,
391           VerifyObjectFlags kVerifyFlags,
392           bool kIsVolatile>
SetFieldBoolean(MemberOffset field_offset,uint8_t new_value)393  inline void Object::SetFieldBoolean(MemberOffset field_offset, uint8_t new_value) {
394    VerifyTransaction<kTransactionActive, kCheckTransaction>();
395    if (kTransactionActive) {
396      Runtime::Current()->RecordWriteFieldBoolean(
397          this,
398          field_offset,
399          GetFieldBoolean<kVerifyFlags, kIsVolatile>(field_offset),
400          kIsVolatile);
401    }
402    Verify<kVerifyFlags>();
403    SetFieldPrimitive<uint8_t, kIsVolatile>(field_offset, new_value);
404  }
405  
406  template<bool kTransactionActive,
407           bool kCheckTransaction,
408           VerifyObjectFlags kVerifyFlags,
409           bool kIsVolatile>
SetFieldByte(MemberOffset field_offset,int8_t new_value)410  inline void Object::SetFieldByte(MemberOffset field_offset, int8_t new_value) {
411    VerifyTransaction<kTransactionActive, kCheckTransaction>();
412    if (kTransactionActive) {
413      Runtime::Current()->RecordWriteFieldByte(this,
414                                               field_offset,
415                                               GetFieldByte<kVerifyFlags, kIsVolatile>(field_offset),
416                                               kIsVolatile);
417    }
418    Verify<kVerifyFlags>();
419    SetFieldPrimitive<int8_t, kIsVolatile>(field_offset, new_value);
420  }
421  
422  template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
SetFieldBooleanVolatile(MemberOffset field_offset,uint8_t new_value)423  inline void Object::SetFieldBooleanVolatile(MemberOffset field_offset, uint8_t new_value) {
424    return SetFieldBoolean<kTransactionActive, kCheckTransaction, kVerifyFlags, true>(
425        field_offset, new_value);
426  }
427  
428  template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
SetFieldByteVolatile(MemberOffset field_offset,int8_t new_value)429  inline void Object::SetFieldByteVolatile(MemberOffset field_offset, int8_t new_value) {
430    return SetFieldByte<kTransactionActive, kCheckTransaction, kVerifyFlags, true>(
431        field_offset, new_value);
432  }
433  
434  template<VerifyObjectFlags kVerifyFlags, bool kIsVolatile>
GetFieldChar(MemberOffset field_offset)435  inline uint16_t Object::GetFieldChar(MemberOffset field_offset) {
436    Verify<kVerifyFlags>();
437    return GetFieldPrimitive<uint16_t, kIsVolatile>(field_offset);
438  }
439  
440  template<VerifyObjectFlags kVerifyFlags, bool kIsVolatile>
GetFieldShort(MemberOffset field_offset)441  inline int16_t Object::GetFieldShort(MemberOffset field_offset) {
442    Verify<kVerifyFlags>();
443    return GetFieldPrimitive<int16_t, kIsVolatile>(field_offset);
444  }
445  
446  template<VerifyObjectFlags kVerifyFlags>
GetFieldCharVolatile(MemberOffset field_offset)447  inline uint16_t Object::GetFieldCharVolatile(MemberOffset field_offset) {
448    return GetFieldChar<kVerifyFlags, true>(field_offset);
449  }
450  
451  template<VerifyObjectFlags kVerifyFlags>
GetFieldShortVolatile(MemberOffset field_offset)452  inline int16_t Object::GetFieldShortVolatile(MemberOffset field_offset) {
453    return GetFieldShort<kVerifyFlags, true>(field_offset);
454  }
455  
456  template<bool kTransactionActive,
457           bool kCheckTransaction,
458           VerifyObjectFlags kVerifyFlags,
459           bool kIsVolatile>
SetFieldChar(MemberOffset field_offset,uint16_t new_value)460  inline void Object::SetFieldChar(MemberOffset field_offset, uint16_t new_value) {
461    VerifyTransaction<kTransactionActive, kCheckTransaction>();
462    if (kTransactionActive) {
463      Runtime::Current()->RecordWriteFieldChar(this,
464                                               field_offset,
465                                               GetFieldChar<kVerifyFlags, kIsVolatile>(field_offset),
466                                               kIsVolatile);
467    }
468    Verify<kVerifyFlags>();
469    SetFieldPrimitive<uint16_t, kIsVolatile>(field_offset, new_value);
470  }
471  
472  template<bool kTransactionActive,
473           bool kCheckTransaction,
474           VerifyObjectFlags kVerifyFlags,
475           bool kIsVolatile>
SetFieldShort(MemberOffset field_offset,int16_t new_value)476  inline void Object::SetFieldShort(MemberOffset field_offset, int16_t new_value) {
477    VerifyTransaction<kTransactionActive, kCheckTransaction>();
478    if (kTransactionActive) {
479      Runtime::Current()->RecordWriteFieldChar(this,
480                                               field_offset,
481                                               GetFieldShort<kVerifyFlags, kIsVolatile>(field_offset),
482                                               kIsVolatile);
483    }
484    Verify<kVerifyFlags>();
485    SetFieldPrimitive<int16_t, kIsVolatile>(field_offset, new_value);
486  }
487  
488  template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
SetFieldCharVolatile(MemberOffset field_offset,uint16_t new_value)489  inline void Object::SetFieldCharVolatile(MemberOffset field_offset, uint16_t new_value) {
490    return SetFieldChar<kTransactionActive, kCheckTransaction, kVerifyFlags, true>(
491        field_offset, new_value);
492  }
493  
494  template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
SetFieldShortVolatile(MemberOffset field_offset,int16_t new_value)495  inline void Object::SetFieldShortVolatile(MemberOffset field_offset, int16_t new_value) {
496    return SetFieldShort<kTransactionActive, kCheckTransaction, kVerifyFlags, true>(
497        field_offset, new_value);
498  }
499  
500  template<bool kTransactionActive,
501           bool kCheckTransaction,
502           VerifyObjectFlags kVerifyFlags,
503           bool kIsVolatile>
SetField32(MemberOffset field_offset,int32_t new_value)504  inline void Object::SetField32(MemberOffset field_offset, int32_t new_value) {
505    VerifyTransaction<kTransactionActive, kCheckTransaction>();
506    if (kTransactionActive) {
507      Runtime::Current()->RecordWriteField32(this,
508                                             field_offset,
509                                             GetField32<kVerifyFlags, kIsVolatile>(field_offset),
510                                             kIsVolatile);
511    }
512    Verify<kVerifyFlags>();
513    SetFieldPrimitive<int32_t, kIsVolatile>(field_offset, new_value);
514  }
515  
516  template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
SetField32Volatile(MemberOffset field_offset,int32_t new_value)517  inline void Object::SetField32Volatile(MemberOffset field_offset, int32_t new_value) {
518    SetField32<kTransactionActive, kCheckTransaction, kVerifyFlags, true>(field_offset, new_value);
519  }
520  
521  template<bool kCheckTransaction, VerifyObjectFlags kVerifyFlags, bool kIsVolatile>
SetField32Transaction(MemberOffset field_offset,int32_t new_value)522  inline void Object::SetField32Transaction(MemberOffset field_offset, int32_t new_value) {
523    if (Runtime::Current()->IsActiveTransaction()) {
524      SetField32<true, kCheckTransaction, kVerifyFlags, kIsVolatile>(field_offset, new_value);
525    } else {
526      SetField32<false, kCheckTransaction, kVerifyFlags, kIsVolatile>(field_offset, new_value);
527    }
528  }
529  
530  template<bool kTransactionActive,
531           bool kCheckTransaction,
532           VerifyObjectFlags kVerifyFlags,
533           bool kIsVolatile>
SetField64(MemberOffset field_offset,int64_t new_value)534  inline void Object::SetField64(MemberOffset field_offset, int64_t new_value) {
535    VerifyTransaction<kTransactionActive, kCheckTransaction>();
536    if (kTransactionActive) {
537      Runtime::Current()->RecordWriteField64(this,
538                                             field_offset,
539                                             GetField64<kVerifyFlags, kIsVolatile>(field_offset),
540                                             kIsVolatile);
541    }
542    Verify<kVerifyFlags>();
543    SetFieldPrimitive<int64_t, kIsVolatile>(field_offset, new_value);
544  }
545  
546  template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
SetField64Volatile(MemberOffset field_offset,int64_t new_value)547  inline void Object::SetField64Volatile(MemberOffset field_offset, int64_t new_value) {
548    return SetField64<kTransactionActive, kCheckTransaction, kVerifyFlags, true>(field_offset,
549                                                                                 new_value);
550  }
551  
552  template<bool kCheckTransaction, VerifyObjectFlags kVerifyFlags, bool kIsVolatile>
SetField64Transaction(MemberOffset field_offset,int32_t new_value)553  inline void Object::SetField64Transaction(MemberOffset field_offset, int32_t new_value) {
554    if (Runtime::Current()->IsActiveTransaction()) {
555      SetField64<true, kCheckTransaction, kVerifyFlags, kIsVolatile>(field_offset, new_value);
556    } else {
557      SetField64<false, kCheckTransaction, kVerifyFlags, kIsVolatile>(field_offset, new_value);
558    }
559  }
560  
561  template<typename kSize>
GetFieldAcquire(MemberOffset field_offset)562  inline kSize Object::GetFieldAcquire(MemberOffset field_offset) {
563    const uint8_t* raw_addr = reinterpret_cast<const uint8_t*>(this) + field_offset.Int32Value();
564    const kSize* addr = reinterpret_cast<const kSize*>(raw_addr);
565    return reinterpret_cast<const Atomic<kSize>*>(addr)->load(std::memory_order_acquire);
566  }
567  
568  template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
CasFieldWeakSequentiallyConsistent64(MemberOffset field_offset,int64_t old_value,int64_t new_value)569  inline bool Object::CasFieldWeakSequentiallyConsistent64(MemberOffset field_offset,
570                                                           int64_t old_value,
571                                                           int64_t new_value) {
572    VerifyTransaction<kTransactionActive, kCheckTransaction>();
573    if (kTransactionActive) {
574      Runtime::Current()->RecordWriteField64(this, field_offset, old_value, true);
575    }
576    Verify<kVerifyFlags>();
577    uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
578    Atomic<int64_t>* atomic_addr = reinterpret_cast<Atomic<int64_t>*>(raw_addr);
579    return atomic_addr->CompareAndSetWeakSequentiallyConsistent(old_value, new_value);
580  }
581  
582  template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
CasFieldStrongSequentiallyConsistent64(MemberOffset field_offset,int64_t old_value,int64_t new_value)583  inline bool Object::CasFieldStrongSequentiallyConsistent64(MemberOffset field_offset,
584                                                             int64_t old_value,
585                                                             int64_t new_value) {
586    VerifyTransaction<kTransactionActive, kCheckTransaction>();
587    if (kTransactionActive) {
588      Runtime::Current()->RecordWriteField64(this, field_offset, old_value, true);
589    }
590    Verify<kVerifyFlags>();
591    uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
592    Atomic<int64_t>* atomic_addr = reinterpret_cast<Atomic<int64_t>*>(raw_addr);
593    return atomic_addr->CompareAndSetStrongSequentiallyConsistent(old_value, new_value);
594  }
595  
596  /*
597   * Returns a pointer to an object representing what the field points to, not an
598   * object representing the field.
599   */
600  template<class T,
601           VerifyObjectFlags kVerifyFlags,
602           ReadBarrierOption kReadBarrierOption,
603           bool kIsVolatile>
GetFieldObject(MemberOffset field_offset)604  inline T* Object::GetFieldObject(MemberOffset field_offset) {
605    Verify<kVerifyFlags>();
606    uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
607    HeapReference<T>* objref_addr = reinterpret_cast<HeapReference<T>*>(raw_addr);
608    T* result = ReadBarrier::Barrier<T, kIsVolatile, kReadBarrierOption>(
609        this,
610        field_offset,
611        objref_addr);
612    VerifyRead<kVerifyFlags>(result);
613    return result;
614  }
615  
616  template<class T, VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
GetFieldObjectVolatile(MemberOffset field_offset)617  inline T* Object::GetFieldObjectVolatile(MemberOffset field_offset) {
618    return GetFieldObject<T, kVerifyFlags, kReadBarrierOption, true>(field_offset);
619  }
620  
621  template<bool kTransactionActive,
622           bool kCheckTransaction,
623           VerifyObjectFlags kVerifyFlags,
624           bool kIsVolatile>
SetFieldObjectWithoutWriteBarrier(MemberOffset field_offset,ObjPtr<Object> new_value)625  inline void Object::SetFieldObjectWithoutWriteBarrier(MemberOffset field_offset,
626                                                        ObjPtr<Object> new_value) {
627    VerifyTransaction<kTransactionActive, kCheckTransaction>();
628    if (kTransactionActive) {
629      ObjPtr<Object> obj;
630      if (kIsVolatile) {
631        obj = GetFieldObjectVolatile<Object>(field_offset);
632      } else {
633        obj = GetFieldObject<Object>(field_offset);
634      }
635      Runtime::Current()->RecordWriteFieldReference(this, field_offset, obj, true);
636    }
637    Verify<kVerifyFlags>();
638    VerifyWrite<kVerifyFlags>(new_value);
639    uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
640    HeapReference<Object>* objref_addr = reinterpret_cast<HeapReference<Object>*>(raw_addr);
641    objref_addr->Assign<kIsVolatile>(new_value.Ptr());
642  }
643  
644  template<bool kTransactionActive,
645           bool kCheckTransaction,
646           VerifyObjectFlags kVerifyFlags,
647           bool kIsVolatile>
SetFieldObject(MemberOffset field_offset,ObjPtr<Object> new_value)648  inline void Object::SetFieldObject(MemberOffset field_offset, ObjPtr<Object> new_value) {
649    SetFieldObjectWithoutWriteBarrier<kTransactionActive, kCheckTransaction, kVerifyFlags,
650        kIsVolatile>(field_offset, new_value);
651    if (new_value != nullptr) {
652      WriteBarrier::ForFieldWrite<WriteBarrier::kWithoutNullCheck>(this, field_offset, new_value);
653      // TODO: Check field assignment could theoretically cause thread suspension, TODO: fix this.
654      CheckFieldAssignment(field_offset, new_value);
655    }
656  }
657  
658  template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
SetFieldObjectVolatile(MemberOffset field_offset,ObjPtr<Object> new_value)659  inline void Object::SetFieldObjectVolatile(MemberOffset field_offset, ObjPtr<Object> new_value) {
660    SetFieldObject<kTransactionActive, kCheckTransaction, kVerifyFlags, true>(field_offset,
661                                                                              new_value);
662  }
663  
664  template<bool kCheckTransaction, VerifyObjectFlags kVerifyFlags, bool kIsVolatile>
SetFieldObjectTransaction(MemberOffset field_offset,ObjPtr<Object> new_value)665  inline void Object::SetFieldObjectTransaction(MemberOffset field_offset, ObjPtr<Object> new_value) {
666    if (Runtime::Current()->IsActiveTransaction()) {
667      SetFieldObject<true, kCheckTransaction, kVerifyFlags, kIsVolatile>(field_offset, new_value);
668    } else {
669      SetFieldObject<false, kCheckTransaction, kVerifyFlags, kIsVolatile>(field_offset, new_value);
670    }
671  }
672  
673  template <VerifyObjectFlags kVerifyFlags>
GetFieldObjectReferenceAddr(MemberOffset field_offset)674  inline HeapReference<Object>* Object::GetFieldObjectReferenceAddr(MemberOffset field_offset) {
675    Verify<kVerifyFlags>();
676    return reinterpret_cast<HeapReference<Object>*>(reinterpret_cast<uint8_t*>(this) +
677        field_offset.Int32Value());
678  }
679  
680  template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
CasFieldObjectWithoutWriteBarrier(MemberOffset field_offset,ObjPtr<Object> old_value,ObjPtr<Object> new_value,CASMode mode,std::memory_order memory_order)681  inline bool Object::CasFieldObjectWithoutWriteBarrier(MemberOffset field_offset,
682                                                        ObjPtr<Object> old_value,
683                                                        ObjPtr<Object> new_value,
684                                                        CASMode mode,
685                                                        std::memory_order memory_order) {
686    VerifyTransaction<kTransactionActive, kCheckTransaction>();
687    VerifyCAS<kVerifyFlags>(new_value, old_value);
688    if (kTransactionActive) {
689      Runtime::Current()->RecordWriteFieldReference(this, field_offset, old_value, true);
690    }
691    uint32_t old_ref(PtrCompression<kPoisonHeapReferences, Object>::Compress(old_value));
692    uint32_t new_ref(PtrCompression<kPoisonHeapReferences, Object>::Compress(new_value));
693    uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
694    Atomic<uint32_t>* atomic_addr = reinterpret_cast<Atomic<uint32_t>*>(raw_addr);
695    return atomic_addr->CompareAndSet(old_ref, new_ref, mode, memory_order);
696  }
697  
698  template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
CasFieldObject(MemberOffset field_offset,ObjPtr<Object> old_value,ObjPtr<Object> new_value,CASMode mode,std::memory_order memory_order)699  inline bool Object::CasFieldObject(MemberOffset field_offset,
700                                     ObjPtr<Object> old_value,
701                                     ObjPtr<Object> new_value,
702                                     CASMode mode,
703                                     std::memory_order memory_order) {
704    bool success = CasFieldObjectWithoutWriteBarrier<
705        kTransactionActive, kCheckTransaction, kVerifyFlags>(field_offset,
706                                                             old_value,
707                                                             new_value,
708                                                             mode,
709                                                             memory_order);
710    if (success) {
711      WriteBarrier::ForFieldWrite(this, field_offset, new_value);
712    }
713    return success;
714  }
715  
716  template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
CompareAndExchangeFieldObject(MemberOffset field_offset,ObjPtr<Object> old_value,ObjPtr<Object> new_value)717  inline ObjPtr<Object> Object::CompareAndExchangeFieldObject(MemberOffset field_offset,
718                                                              ObjPtr<Object> old_value,
719                                                              ObjPtr<Object> new_value) {
720    VerifyTransaction<kTransactionActive, kCheckTransaction>();
721    VerifyCAS<kVerifyFlags>(new_value, old_value);
722    uint32_t old_ref(PtrCompression<kPoisonHeapReferences, Object>::Compress(old_value));
723    uint32_t new_ref(PtrCompression<kPoisonHeapReferences, Object>::Compress(new_value));
724    uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
725    Atomic<uint32_t>* atomic_addr = reinterpret_cast<Atomic<uint32_t>*>(raw_addr);
726    bool success = atomic_addr->compare_exchange_strong(old_ref, new_ref, std::memory_order_seq_cst);
727    ObjPtr<Object> witness_value(PtrCompression<kPoisonHeapReferences, Object>::Decompress(old_ref));
728    if (kIsDebugBuild) {
729      // Ensure caller has done read barrier on the reference field so it's in the to-space.
730      ReadBarrier::AssertToSpaceInvariant(witness_value.Ptr());
731    }
732    if (success) {
733      if (kTransactionActive) {
734        Runtime::Current()->RecordWriteFieldReference(this, field_offset, witness_value, true);
735      }
736      WriteBarrier::ForFieldWrite(this, field_offset, new_value);
737    }
738    VerifyRead<kVerifyFlags>(witness_value);
739    return witness_value;
740  }
741  
742  template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
ExchangeFieldObject(MemberOffset field_offset,ObjPtr<Object> new_value)743  inline ObjPtr<Object> Object::ExchangeFieldObject(MemberOffset field_offset,
744                                                    ObjPtr<Object> new_value) {
745    VerifyTransaction<kTransactionActive, kCheckTransaction>();
746    VerifyCAS<kVerifyFlags>(new_value, /*old_value=*/ nullptr);
747  
748    uint32_t new_ref(PtrCompression<kPoisonHeapReferences, Object>::Compress(new_value));
749    uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
750    Atomic<uint32_t>* atomic_addr = reinterpret_cast<Atomic<uint32_t>*>(raw_addr);
751    uint32_t old_ref = atomic_addr->exchange(new_ref, std::memory_order_seq_cst);
752    ObjPtr<Object> old_value(PtrCompression<kPoisonHeapReferences, Object>::Decompress(old_ref));
753    if (kIsDebugBuild) {
754      // Ensure caller has done read barrier on the reference field so it's in the to-space.
755      ReadBarrier::AssertToSpaceInvariant(old_value.Ptr());
756    }
757    if (kTransactionActive) {
758      Runtime::Current()->RecordWriteFieldReference(this, field_offset, old_value, true);
759    }
760    WriteBarrier::ForFieldWrite(this, field_offset, new_value);
761    VerifyRead<kVerifyFlags>(old_value);
762    return old_value;
763  }
764  
765  template<typename T, VerifyObjectFlags kVerifyFlags>
GetPrimitiveFieldViaAccessor(MemberOffset field_offset,Accessor<T> * accessor)766  inline void Object::GetPrimitiveFieldViaAccessor(MemberOffset field_offset, Accessor<T>* accessor) {
767    Verify<kVerifyFlags>();
768    uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
769    T* addr = reinterpret_cast<T*>(raw_addr);
770    accessor->Access(addr);
771  }
772  
773  template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
UpdateFieldBooleanViaAccessor(MemberOffset field_offset,Accessor<uint8_t> * accessor)774  inline void Object::UpdateFieldBooleanViaAccessor(MemberOffset field_offset,
775                                                    Accessor<uint8_t>* accessor) {
776    VerifyTransaction<kTransactionActive, kCheckTransaction>();
777    if (kTransactionActive) {
778      static const bool kIsVolatile = true;
779      uint8_t old_value = GetFieldBoolean<kVerifyFlags, kIsVolatile>(field_offset);
780      Runtime::Current()->RecordWriteFieldBoolean(this, field_offset, old_value, kIsVolatile);
781    }
782    Verify<kVerifyFlags>();
783    uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
784    uint8_t* addr = raw_addr;
785    accessor->Access(addr);
786  }
787  
788  template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
UpdateFieldByteViaAccessor(MemberOffset field_offset,Accessor<int8_t> * accessor)789  inline void Object::UpdateFieldByteViaAccessor(MemberOffset field_offset,
790                                                 Accessor<int8_t>* accessor) {
791    VerifyTransaction<kTransactionActive, kCheckTransaction>();
792    if (kTransactionActive) {
793      static const bool kIsVolatile = true;
794      int8_t old_value = GetFieldByte<kVerifyFlags, kIsVolatile>(field_offset);
795      Runtime::Current()->RecordWriteFieldByte(this, field_offset, old_value, kIsVolatile);
796    }
797    Verify<kVerifyFlags>();
798    uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
799    int8_t* addr = reinterpret_cast<int8_t*>(raw_addr);
800    accessor->Access(addr);
801  }
802  
803  template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
UpdateFieldCharViaAccessor(MemberOffset field_offset,Accessor<uint16_t> * accessor)804  inline void Object::UpdateFieldCharViaAccessor(MemberOffset field_offset,
805                                                 Accessor<uint16_t>* accessor) {
806    VerifyTransaction<kTransactionActive, kCheckTransaction>();
807    if (kTransactionActive) {
808      static const bool kIsVolatile = true;
809      uint16_t old_value = GetFieldChar<kVerifyFlags, kIsVolatile>(field_offset);
810      Runtime::Current()->RecordWriteFieldChar(this, field_offset, old_value, kIsVolatile);
811    }
812    Verify<kVerifyFlags>();
813    uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
814    uint16_t* addr = reinterpret_cast<uint16_t*>(raw_addr);
815    accessor->Access(addr);
816  }
817  
818  template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
UpdateFieldShortViaAccessor(MemberOffset field_offset,Accessor<int16_t> * accessor)819  inline void Object::UpdateFieldShortViaAccessor(MemberOffset field_offset,
820                                                  Accessor<int16_t>* accessor) {
821    VerifyTransaction<kTransactionActive, kCheckTransaction>();
822    if (kTransactionActive) {
823      static const bool kIsVolatile = true;
824      int16_t old_value = GetFieldShort<kVerifyFlags, kIsVolatile>(field_offset);
825      Runtime::Current()->RecordWriteFieldShort(this, field_offset, old_value, kIsVolatile);
826    }
827    Verify<kVerifyFlags>();
828    uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
829    int16_t* addr = reinterpret_cast<int16_t*>(raw_addr);
830    accessor->Access(addr);
831  }
832  
833  template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
UpdateField32ViaAccessor(MemberOffset field_offset,Accessor<int32_t> * accessor)834  inline void Object::UpdateField32ViaAccessor(MemberOffset field_offset,
835                                               Accessor<int32_t>* accessor) {
836    VerifyTransaction<kTransactionActive, kCheckTransaction>();
837    if (kTransactionActive) {
838      static const bool kIsVolatile = true;
839      int32_t old_value = GetField32<kVerifyFlags, kIsVolatile>(field_offset);
840      Runtime::Current()->RecordWriteField32(this, field_offset, old_value, kIsVolatile);
841    }
842    Verify<kVerifyFlags>();
843    uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
844    int32_t* addr = reinterpret_cast<int32_t*>(raw_addr);
845    accessor->Access(addr);
846  }
847  
848  template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
UpdateField64ViaAccessor(MemberOffset field_offset,Accessor<int64_t> * accessor)849  inline void Object::UpdateField64ViaAccessor(MemberOffset field_offset,
850                                               Accessor<int64_t>* accessor) {
851    VerifyTransaction<kTransactionActive, kCheckTransaction>();
852    if (kTransactionActive) {
853      static const bool kIsVolatile = true;
854      int64_t old_value = GetField64<kVerifyFlags, kIsVolatile>(field_offset);
855      Runtime::Current()->RecordWriteField64(this, field_offset, old_value, kIsVolatile);
856    }
857    Verify<kVerifyFlags>();
858    uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
859    int64_t* addr = reinterpret_cast<int64_t*>(raw_addr);
860    accessor->Access(addr);
861  }
862  
863  template<bool kIsStatic,
864           VerifyObjectFlags kVerifyFlags,
865           ReadBarrierOption kReadBarrierOption,
866           typename Visitor>
VisitFieldsReferences(uint32_t ref_offsets,const Visitor & visitor)867  inline void Object::VisitFieldsReferences(uint32_t ref_offsets, const Visitor& visitor) {
868    if (!kIsStatic && (ref_offsets != mirror::Class::kClassWalkSuper)) {
869      // Instance fields and not the slow-path.
870      uint32_t field_offset = mirror::kObjectHeaderSize;
871      while (ref_offsets != 0) {
872        if ((ref_offsets & 1) != 0) {
873          visitor(this, MemberOffset(field_offset), kIsStatic);
874        }
875        ref_offsets >>= 1;
876        field_offset += sizeof(mirror::HeapReference<mirror::Object>);
877      }
878    } else {
879      // There is no reference offset bitmap. In the non-static case, walk up the class
880      // inheritance hierarchy and find reference offsets the hard way. In the static case, just
881      // consider this class.
882      for (ObjPtr<Class> klass = kIsStatic
883              ? ObjPtr<Class>::DownCast(this)
884              : GetClass<kVerifyFlags, kReadBarrierOption>();
885          klass != nullptr;
886          klass = kIsStatic ? nullptr : klass->GetSuperClass<kVerifyFlags, kReadBarrierOption>()) {
887        const size_t num_reference_fields =
888            kIsStatic ? klass->NumReferenceStaticFields() : klass->NumReferenceInstanceFields();
889        if (num_reference_fields == 0u) {
890          continue;
891        }
892        // Presumably GC can happen when we are cross compiling, it should not cause performance
893        // problems to do pointer size logic.
894        MemberOffset field_offset = kIsStatic
895            ? klass->GetFirstReferenceStaticFieldOffset<kVerifyFlags>(
896                Runtime::Current()->GetClassLinker()->GetImagePointerSize())
897            : klass->GetFirstReferenceInstanceFieldOffset<kVerifyFlags, kReadBarrierOption>();
898        for (size_t i = 0u; i < num_reference_fields; ++i) {
899          // TODO: Do a simpler check?
900          if (field_offset.Uint32Value() != ClassOffset().Uint32Value()) {
901            visitor(this, field_offset, kIsStatic);
902          }
903          field_offset = MemberOffset(field_offset.Uint32Value() +
904                                      sizeof(mirror::HeapReference<mirror::Object>));
905        }
906      }
907    }
908  }
909  
910  template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption, typename Visitor>
VisitInstanceFieldsReferences(ObjPtr<Class> klass,const Visitor & visitor)911  inline void Object::VisitInstanceFieldsReferences(ObjPtr<Class> klass, const Visitor& visitor) {
912    VisitFieldsReferences<false, kVerifyFlags, kReadBarrierOption>(
913        klass->GetReferenceInstanceOffsets<kVerifyFlags>(), visitor);
914  }
915  
916  template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption, typename Visitor>
VisitStaticFieldsReferences(ObjPtr<Class> klass,const Visitor & visitor)917  inline void Object::VisitStaticFieldsReferences(ObjPtr<Class> klass, const Visitor& visitor) {
918    DCHECK(!klass->IsTemp<kVerifyFlags>());
919    klass->VisitFieldsReferences<true, kVerifyFlags, kReadBarrierOption>(0, visitor);
920  }
921  
922  template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
IsClassLoader()923  inline bool Object::IsClassLoader() {
924    return GetClass<kVerifyFlags, kReadBarrierOption>()->template IsClassLoaderClass<kVerifyFlags>();
925  }
926  
927  template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
AsClassLoader()928  inline ObjPtr<ClassLoader> Object::AsClassLoader() {
929    DCHECK((IsClassLoader<kVerifyFlags, kReadBarrierOption>()));
930    return ObjPtr<ClassLoader>::DownCast(this);
931  }
932  
933  template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
IsDexCache()934  inline bool Object::IsDexCache() {
935    return GetClass<kVerifyFlags, kReadBarrierOption>()->template IsDexCacheClass<kVerifyFlags>();
936  }
937  
938  template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
AsDexCache()939  inline ObjPtr<mirror::DexCache> Object::AsDexCache() {
940    DCHECK((IsDexCache<kVerifyFlags, kReadBarrierOption>()));
941    return ObjPtr<DexCache>::DownCast(this);
942  }
943  
944  template<bool kTransactionActive, bool kCheckTransaction>
VerifyTransaction()945  inline void Object::VerifyTransaction() {
946    if (kCheckTransaction) {
947      DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
948    }
949  }
950  
951  }  // namespace mirror
952  }  // namespace art
953  
954  #endif  // ART_RUNTIME_MIRROR_OBJECT_INL_H_
955