Home | History | Annotate | Download | only in mirror
      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 "art_field.h"
     23 #include "art_method.h"
     24 #include "atomic.h"
     25 #include "array-inl.h"
     26 #include "class-inl.h"
     27 #include "class_flags.h"
     28 #include "class_linker.h"
     29 #include "class_loader-inl.h"
     30 #include "dex_cache-inl.h"
     31 #include "lock_word-inl.h"
     32 #include "monitor.h"
     33 #include "object_array-inl.h"
     34 #include "object_reference-inl.h"
     35 #include "object-readbarrier-inl.h"
     36 #include "obj_ptr-inl.h"
     37 #include "read_barrier-inl.h"
     38 #include "reference.h"
     39 #include "runtime.h"
     40 #include "string-inl.h"
     41 #include "throwable.h"
     42 
     43 namespace art {
     44 namespace mirror {
     45 
     46 inline uint32_t Object::ClassSize(PointerSize pointer_size) {
     47   uint32_t vtable_entries = kVTableLength;
     48   return Class::ComputeClassSize(true, vtable_entries, 0, 0, 0, 0, 0, pointer_size);
     49 }
     50 
     51 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
     52 inline Class* Object::GetClass() {
     53   return GetFieldObject<Class, kVerifyFlags, kReadBarrierOption>(
     54       OFFSET_OF_OBJECT_MEMBER(Object, klass_));
     55 }
     56 
     57 template<VerifyObjectFlags kVerifyFlags>
     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,
     65       static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis)>(
     66       OFFSET_OF_OBJECT_MEMBER(Object, klass_), new_klass);
     67 }
     68 
     69 template<VerifyObjectFlags kVerifyFlags>
     70 inline void Object::SetLockWord(LockWord new_val, bool as_volatile) {
     71   // Force use of non-transactional mode and do not check.
     72   if (as_volatile) {
     73     SetField32Volatile<false, false, kVerifyFlags>(
     74         OFFSET_OF_OBJECT_MEMBER(Object, monitor_), new_val.GetValue());
     75   } else {
     76     SetField32<false, false, kVerifyFlags>(
     77         OFFSET_OF_OBJECT_MEMBER(Object, monitor_), new_val.GetValue());
     78   }
     79 }
     80 
     81 inline bool Object::CasLockWordWeakSequentiallyConsistent(LockWord old_val, LockWord new_val) {
     82   // Force use of non-transactional mode and do not check.
     83   return CasFieldWeakSequentiallyConsistent32<false, false>(
     84       OFFSET_OF_OBJECT_MEMBER(Object, monitor_), old_val.GetValue(), new_val.GetValue());
     85 }
     86 
     87 inline bool Object::CasLockWordWeakAcquire(LockWord old_val, LockWord new_val) {
     88   // Force use of non-transactional mode and do not check.
     89   return CasFieldWeakAcquire32<false, false>(
     90       OFFSET_OF_OBJECT_MEMBER(Object, monitor_), old_val.GetValue(), new_val.GetValue());
     91 }
     92 
     93 inline uint32_t Object::GetLockOwnerThreadId() {
     94   return Monitor::GetLockOwnerThreadId(this);
     95 }
     96 
     97 inline mirror::Object* Object::MonitorEnter(Thread* self) {
     98   return Monitor::MonitorEnter(self, this, /*trylock*/false);
     99 }
    100 
    101 inline mirror::Object* Object::MonitorTryEnter(Thread* self) {
    102   return Monitor::MonitorEnter(self, this, /*trylock*/true);
    103 }
    104 
    105 inline bool Object::MonitorExit(Thread* self) {
    106   return Monitor::MonitorExit(self, this);
    107 }
    108 
    109 inline void Object::Notify(Thread* self) {
    110   Monitor::Notify(self, this);
    111 }
    112 
    113 inline void Object::NotifyAll(Thread* self) {
    114   Monitor::NotifyAll(self, this);
    115 }
    116 
    117 inline void Object::Wait(Thread* self) {
    118   Monitor::Wait(self, this, 0, 0, true, kWaiting);
    119 }
    120 
    121 inline void Object::Wait(Thread* self, int64_t ms, int32_t ns) {
    122   Monitor::Wait(self, this, ms, ns, true, kTimedWaiting);
    123 }
    124 
    125 inline uint32_t Object::GetMarkBit() {
    126 #ifdef USE_READ_BARRIER
    127   return GetLockWord(false).MarkBitState();
    128 #else
    129   LOG(FATAL) << "Unreachable";
    130   UNREACHABLE();
    131 #endif
    132 }
    133 
    134 inline void Object::SetReadBarrierState(uint32_t rb_state) {
    135   if (!kUseBakerReadBarrier) {
    136     LOG(FATAL) << "Unreachable";
    137     UNREACHABLE();
    138   }
    139   DCHECK(ReadBarrier::IsValidReadBarrierState(rb_state)) << rb_state;
    140   LockWord lw = GetLockWord(false);
    141   lw.SetReadBarrierState(rb_state);
    142   SetLockWord(lw, false);
    143 }
    144 
    145 inline void Object::AssertReadBarrierState() const {
    146   CHECK(kUseBakerReadBarrier);
    147   Object* obj = const_cast<Object*>(this);
    148   DCHECK(obj->GetReadBarrierState() == ReadBarrier::WhiteState())
    149       << "Bad Baker pointer: obj=" << reinterpret_cast<void*>(obj)
    150       << " rb_state" << reinterpret_cast<void*>(obj->GetReadBarrierState());
    151 }
    152 
    153 template<VerifyObjectFlags kVerifyFlags>
    154 inline bool Object::VerifierInstanceOf(ObjPtr<Class> klass) {
    155   DCHECK(klass != nullptr);
    156   DCHECK(GetClass<kVerifyFlags>() != nullptr);
    157   return klass->IsInterface() || InstanceOf(klass);
    158 }
    159 
    160 template<VerifyObjectFlags kVerifyFlags>
    161 inline bool Object::InstanceOf(ObjPtr<Class> klass) {
    162   DCHECK(klass != nullptr);
    163   DCHECK(GetClass<kVerifyNone>() != nullptr);
    164   return klass->IsAssignableFrom(GetClass<kVerifyFlags>());
    165 }
    166 
    167 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
    168 inline bool Object::IsClass() {
    169   Class* java_lang_Class = GetClass<kVerifyFlags, kReadBarrierOption>()->
    170       template GetClass<kVerifyFlags, kReadBarrierOption>();
    171   return GetClass<static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis),
    172       kReadBarrierOption>() == java_lang_Class;
    173 }
    174 
    175 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
    176 inline Class* Object::AsClass() {
    177   DCHECK((IsClass<kVerifyFlags, kReadBarrierOption>()));
    178   return down_cast<Class*>(this);
    179 }
    180 
    181 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
    182 inline bool Object::IsObjectArray() {
    183   constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
    184   return IsArrayInstance<kVerifyFlags, kReadBarrierOption>() &&
    185       !GetClass<kNewFlags, kReadBarrierOption>()->
    186           template GetComponentType<kNewFlags, kReadBarrierOption>()->IsPrimitive();
    187 }
    188 
    189 template<class T, VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
    190 inline ObjectArray<T>* Object::AsObjectArray() {
    191   DCHECK((IsObjectArray<kVerifyFlags, kReadBarrierOption>()));
    192   return down_cast<ObjectArray<T>*>(this);
    193 }
    194 
    195 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
    196 inline bool Object::IsArrayInstance() {
    197   return GetClass<kVerifyFlags, kReadBarrierOption>()->
    198       template IsArrayClass<kVerifyFlags, kReadBarrierOption>();
    199 }
    200 
    201 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
    202 inline bool Object::IsReferenceInstance() {
    203   return GetClass<kVerifyFlags, kReadBarrierOption>()->IsTypeOfReferenceClass();
    204 }
    205 
    206 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
    207 inline Reference* Object::AsReference() {
    208   DCHECK((IsReferenceInstance<kVerifyFlags, kReadBarrierOption>()));
    209   return down_cast<Reference*>(this);
    210 }
    211 
    212 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
    213 inline Array* Object::AsArray() {
    214   DCHECK((IsArrayInstance<kVerifyFlags, kReadBarrierOption>()));
    215   return down_cast<Array*>(this);
    216 }
    217 
    218 template<VerifyObjectFlags kVerifyFlags>
    219 inline BooleanArray* Object::AsBooleanArray() {
    220   constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
    221   DCHECK(GetClass<kVerifyFlags>()->IsArrayClass());
    222   DCHECK(GetClass<kNewFlags>()->GetComponentType()->IsPrimitiveBoolean());
    223   return down_cast<BooleanArray*>(this);
    224 }
    225 
    226 template<VerifyObjectFlags kVerifyFlags>
    227 inline ByteArray* Object::AsByteArray() {
    228   constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
    229   DCHECK(GetClass<kVerifyFlags>()->IsArrayClass());
    230   DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveByte());
    231   return down_cast<ByteArray*>(this);
    232 }
    233 
    234 template<VerifyObjectFlags kVerifyFlags>
    235 inline ByteArray* Object::AsByteSizedArray() {
    236   constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
    237   DCHECK(GetClass<kVerifyFlags>()->IsArrayClass());
    238   DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveByte() ||
    239          GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveBoolean());
    240   return down_cast<ByteArray*>(this);
    241 }
    242 
    243 template<VerifyObjectFlags kVerifyFlags>
    244 inline CharArray* Object::AsCharArray() {
    245   constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
    246   DCHECK(GetClass<kVerifyFlags>()->IsArrayClass());
    247   DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveChar());
    248   return down_cast<CharArray*>(this);
    249 }
    250 
    251 template<VerifyObjectFlags kVerifyFlags>
    252 inline ShortArray* Object::AsShortArray() {
    253   constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
    254   DCHECK(GetClass<kVerifyFlags>()->IsArrayClass());
    255   DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveShort());
    256   return down_cast<ShortArray*>(this);
    257 }
    258 
    259 template<VerifyObjectFlags kVerifyFlags>
    260 inline ShortArray* Object::AsShortSizedArray() {
    261   constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
    262   DCHECK(GetClass<kVerifyFlags>()->IsArrayClass());
    263   DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveShort() ||
    264          GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveChar());
    265   return down_cast<ShortArray*>(this);
    266 }
    267 
    268 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
    269 inline bool Object::IsIntArray() {
    270   constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
    271   ObjPtr<Class> klass = GetClass<kVerifyFlags, kReadBarrierOption>();
    272   ObjPtr<Class> component_type = klass->GetComponentType<kVerifyFlags, kReadBarrierOption>();
    273   return component_type != nullptr && component_type->template IsPrimitiveInt<kNewFlags>();
    274 }
    275 
    276 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
    277 inline IntArray* Object::AsIntArray() {
    278   DCHECK((IsIntArray<kVerifyFlags, kReadBarrierOption>()));
    279   return down_cast<IntArray*>(this);
    280 }
    281 
    282 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
    283 inline bool Object::IsLongArray() {
    284   constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
    285   ObjPtr<Class> klass = GetClass<kVerifyFlags, kReadBarrierOption>();
    286   ObjPtr<Class> component_type = klass->GetComponentType<kVerifyFlags, kReadBarrierOption>();
    287   return component_type != nullptr && component_type->template IsPrimitiveLong<kNewFlags>();
    288 }
    289 
    290 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
    291 inline LongArray* Object::AsLongArray() {
    292   DCHECK((IsLongArray<kVerifyFlags, kReadBarrierOption>()));
    293   return down_cast<LongArray*>(this);
    294 }
    295 
    296 template<VerifyObjectFlags kVerifyFlags>
    297 inline bool Object::IsFloatArray() {
    298   constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
    299   auto* component_type = GetClass<kVerifyFlags>()->GetComponentType();
    300   return component_type != nullptr && component_type->template IsPrimitiveFloat<kNewFlags>();
    301 }
    302 
    303 template<VerifyObjectFlags kVerifyFlags>
    304 inline FloatArray* Object::AsFloatArray() {
    305   DCHECK(IsFloatArray<kVerifyFlags>());
    306   constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
    307   DCHECK(GetClass<kVerifyFlags>()->IsArrayClass());
    308   DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveFloat());
    309   return down_cast<FloatArray*>(this);
    310 }
    311 
    312 template<VerifyObjectFlags kVerifyFlags>
    313 inline bool Object::IsDoubleArray() {
    314   constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
    315   auto* component_type = GetClass<kVerifyFlags>()->GetComponentType();
    316   return component_type != nullptr && component_type->template IsPrimitiveDouble<kNewFlags>();
    317 }
    318 
    319 template<VerifyObjectFlags kVerifyFlags>
    320 inline DoubleArray* Object::AsDoubleArray() {
    321   DCHECK(IsDoubleArray<kVerifyFlags>());
    322   constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
    323   DCHECK(GetClass<kVerifyFlags>()->IsArrayClass());
    324   DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveDouble());
    325   return down_cast<DoubleArray*>(this);
    326 }
    327 
    328 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
    329 inline bool Object::IsString() {
    330   return GetClass<kVerifyFlags, kReadBarrierOption>()->IsStringClass();
    331 }
    332 
    333 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
    334 inline String* Object::AsString() {
    335   DCHECK((IsString<kVerifyFlags, kReadBarrierOption>()));
    336   return down_cast<String*>(this);
    337 }
    338 
    339 template<VerifyObjectFlags kVerifyFlags>
    340 inline Throwable* Object::AsThrowable() {
    341   DCHECK(GetClass<kVerifyFlags>()->IsThrowableClass());
    342   return down_cast<Throwable*>(this);
    343 }
    344 
    345 template<VerifyObjectFlags kVerifyFlags>
    346 inline bool Object::IsWeakReferenceInstance() {
    347   return GetClass<kVerifyFlags>()->IsWeakReferenceClass();
    348 }
    349 
    350 template<VerifyObjectFlags kVerifyFlags>
    351 inline bool Object::IsSoftReferenceInstance() {
    352   return GetClass<kVerifyFlags>()->IsSoftReferenceClass();
    353 }
    354 
    355 template<VerifyObjectFlags kVerifyFlags>
    356 inline bool Object::IsFinalizerReferenceInstance() {
    357   return GetClass<kVerifyFlags>()->IsFinalizerReferenceClass();
    358 }
    359 
    360 template<VerifyObjectFlags kVerifyFlags>
    361 inline FinalizerReference* Object::AsFinalizerReference() {
    362   DCHECK(IsFinalizerReferenceInstance<kVerifyFlags>());
    363   return down_cast<FinalizerReference*>(this);
    364 }
    365 
    366 template<VerifyObjectFlags kVerifyFlags>
    367 inline bool Object::IsPhantomReferenceInstance() {
    368   return GetClass<kVerifyFlags>()->IsPhantomReferenceClass();
    369 }
    370 
    371 template<VerifyObjectFlags kVerifyFlags>
    372 inline size_t Object::SizeOf() {
    373   // Read barrier is never required for SizeOf since objects sizes are constant. Reading from-space
    374   // values is OK because of that.
    375   static constexpr ReadBarrierOption kReadBarrierOption = kWithoutReadBarrier;
    376   size_t result;
    377   constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
    378   if (IsArrayInstance<kVerifyFlags, kReadBarrierOption>()) {
    379     result = AsArray<kNewFlags, kReadBarrierOption>()->
    380         template SizeOf<kNewFlags, kReadBarrierOption>();
    381   } else if (IsClass<kNewFlags, kReadBarrierOption>()) {
    382     result = AsClass<kNewFlags, kReadBarrierOption>()->
    383         template SizeOf<kNewFlags, kReadBarrierOption>();
    384   } else if (GetClass<kNewFlags, kReadBarrierOption>()->IsStringClass()) {
    385     result = AsString<kNewFlags, kReadBarrierOption>()->
    386         template SizeOf<kNewFlags>();
    387   } else {
    388     result = GetClass<kNewFlags, kReadBarrierOption>()->
    389         template GetObjectSize<kNewFlags, kReadBarrierOption>();
    390   }
    391   DCHECK_GE(result, sizeof(Object))
    392       << " class=" << Class::PrettyClass(GetClass<kNewFlags, kReadBarrierOption>());
    393   return result;
    394 }
    395 
    396 template<VerifyObjectFlags kVerifyFlags, bool kIsVolatile>
    397 inline uint8_t Object::GetFieldBoolean(MemberOffset field_offset) {
    398   if (kVerifyFlags & kVerifyThis) {
    399     VerifyObject(this);
    400   }
    401   return GetField<uint8_t, kIsVolatile>(field_offset);
    402 }
    403 
    404 template<VerifyObjectFlags kVerifyFlags, bool kIsVolatile>
    405 inline int8_t Object::GetFieldByte(MemberOffset field_offset) {
    406   if (kVerifyFlags & kVerifyThis) {
    407     VerifyObject(this);
    408   }
    409   return GetField<int8_t, kIsVolatile>(field_offset);
    410 }
    411 
    412 template<VerifyObjectFlags kVerifyFlags>
    413 inline uint8_t Object::GetFieldBooleanVolatile(MemberOffset field_offset) {
    414   return GetFieldBoolean<kVerifyFlags, true>(field_offset);
    415 }
    416 
    417 template<VerifyObjectFlags kVerifyFlags>
    418 inline int8_t Object::GetFieldByteVolatile(MemberOffset field_offset) {
    419   return GetFieldByte<kVerifyFlags, true>(field_offset);
    420 }
    421 
    422 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags,
    423     bool kIsVolatile>
    424 inline void Object::SetFieldBoolean(MemberOffset field_offset, uint8_t new_value)
    425     REQUIRES_SHARED(Locks::mutator_lock_) {
    426   if (kCheckTransaction) {
    427     DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
    428   }
    429   if (kTransactionActive) {
    430     Runtime::Current()->RecordWriteFieldBoolean(this, field_offset,
    431                                            GetFieldBoolean<kVerifyFlags, kIsVolatile>(field_offset),
    432                                            kIsVolatile);
    433   }
    434   if (kVerifyFlags & kVerifyThis) {
    435     VerifyObject(this);
    436   }
    437   SetField<uint8_t, kIsVolatile>(field_offset, new_value);
    438 }
    439 
    440 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags,
    441     bool kIsVolatile>
    442 inline void Object::SetFieldByte(MemberOffset field_offset, int8_t new_value)
    443     REQUIRES_SHARED(Locks::mutator_lock_) {
    444   if (kCheckTransaction) {
    445     DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
    446   }
    447   if (kTransactionActive) {
    448     Runtime::Current()->RecordWriteFieldByte(this, field_offset,
    449                                            GetFieldByte<kVerifyFlags, kIsVolatile>(field_offset),
    450                                            kIsVolatile);
    451   }
    452   if (kVerifyFlags & kVerifyThis) {
    453     VerifyObject(this);
    454   }
    455   SetField<int8_t, kIsVolatile>(field_offset, new_value);
    456 }
    457 
    458 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
    459 inline void Object::SetFieldBooleanVolatile(MemberOffset field_offset, uint8_t new_value) {
    460   return SetFieldBoolean<kTransactionActive, kCheckTransaction, kVerifyFlags, true>(
    461       field_offset, new_value);
    462 }
    463 
    464 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
    465 inline void Object::SetFieldByteVolatile(MemberOffset field_offset, int8_t new_value) {
    466   return SetFieldByte<kTransactionActive, kCheckTransaction, kVerifyFlags, true>(
    467       field_offset, new_value);
    468 }
    469 
    470 template<VerifyObjectFlags kVerifyFlags, bool kIsVolatile>
    471 inline uint16_t Object::GetFieldChar(MemberOffset field_offset) {
    472   if (kVerifyFlags & kVerifyThis) {
    473     VerifyObject(this);
    474   }
    475   return GetField<uint16_t, kIsVolatile>(field_offset);
    476 }
    477 
    478 template<VerifyObjectFlags kVerifyFlags, bool kIsVolatile>
    479 inline int16_t Object::GetFieldShort(MemberOffset field_offset) {
    480   if (kVerifyFlags & kVerifyThis) {
    481     VerifyObject(this);
    482   }
    483   return GetField<int16_t, kIsVolatile>(field_offset);
    484 }
    485 
    486 template<VerifyObjectFlags kVerifyFlags>
    487 inline uint16_t Object::GetFieldCharVolatile(MemberOffset field_offset) {
    488   return GetFieldChar<kVerifyFlags, true>(field_offset);
    489 }
    490 
    491 template<VerifyObjectFlags kVerifyFlags>
    492 inline int16_t Object::GetFieldShortVolatile(MemberOffset field_offset) {
    493   return GetFieldShort<kVerifyFlags, true>(field_offset);
    494 }
    495 
    496 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags,
    497     bool kIsVolatile>
    498 inline void Object::SetFieldChar(MemberOffset field_offset, uint16_t new_value) {
    499   if (kCheckTransaction) {
    500     DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
    501   }
    502   if (kTransactionActive) {
    503     Runtime::Current()->RecordWriteFieldChar(this, field_offset,
    504                                            GetFieldChar<kVerifyFlags, kIsVolatile>(field_offset),
    505                                            kIsVolatile);
    506   }
    507   if (kVerifyFlags & kVerifyThis) {
    508     VerifyObject(this);
    509   }
    510   SetField<uint16_t, kIsVolatile>(field_offset, new_value);
    511 }
    512 
    513 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags,
    514     bool kIsVolatile>
    515 inline void Object::SetFieldShort(MemberOffset field_offset, int16_t new_value) {
    516   if (kCheckTransaction) {
    517     DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
    518   }
    519   if (kTransactionActive) {
    520     Runtime::Current()->RecordWriteFieldChar(this, field_offset,
    521                                            GetFieldShort<kVerifyFlags, kIsVolatile>(field_offset),
    522                                            kIsVolatile);
    523   }
    524   if (kVerifyFlags & kVerifyThis) {
    525     VerifyObject(this);
    526   }
    527   SetField<int16_t, kIsVolatile>(field_offset, new_value);
    528 }
    529 
    530 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
    531 inline void Object::SetFieldCharVolatile(MemberOffset field_offset, uint16_t new_value) {
    532   return SetFieldChar<kTransactionActive, kCheckTransaction, kVerifyFlags, true>(
    533       field_offset, new_value);
    534 }
    535 
    536 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
    537 inline void Object::SetFieldShortVolatile(MemberOffset field_offset, int16_t new_value) {
    538   return SetFieldShort<kTransactionActive, kCheckTransaction, kVerifyFlags, true>(
    539       field_offset, new_value);
    540 }
    541 
    542 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags,
    543     bool kIsVolatile>
    544 inline void Object::SetField32(MemberOffset field_offset, int32_t new_value) {
    545   if (kCheckTransaction) {
    546     DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
    547   }
    548   if (kTransactionActive) {
    549     Runtime::Current()->RecordWriteField32(this, field_offset,
    550                                            GetField32<kVerifyFlags, kIsVolatile>(field_offset),
    551                                            kIsVolatile);
    552   }
    553   if (kVerifyFlags & kVerifyThis) {
    554     VerifyObject(this);
    555   }
    556   SetField<int32_t, kIsVolatile>(field_offset, new_value);
    557 }
    558 
    559 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
    560 inline void Object::SetField32Volatile(MemberOffset field_offset, int32_t new_value) {
    561   SetField32<kTransactionActive, kCheckTransaction, kVerifyFlags, true>(field_offset, new_value);
    562 }
    563 
    564 // TODO: Pass memory_order_ and strong/weak as arguments to avoid code duplication?
    565 
    566 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
    567 inline bool Object::CasFieldWeakSequentiallyConsistent32(MemberOffset field_offset,
    568                                                          int32_t old_value, int32_t new_value) {
    569   if (kCheckTransaction) {
    570     DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
    571   }
    572   if (kTransactionActive) {
    573     Runtime::Current()->RecordWriteField32(this, field_offset, old_value, true);
    574   }
    575   if (kVerifyFlags & kVerifyThis) {
    576     VerifyObject(this);
    577   }
    578   uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
    579   AtomicInteger* atomic_addr = reinterpret_cast<AtomicInteger*>(raw_addr);
    580 
    581   return atomic_addr->CompareExchangeWeakSequentiallyConsistent(old_value, new_value);
    582 }
    583 
    584 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
    585 inline bool Object::CasFieldWeakAcquire32(MemberOffset field_offset,
    586                                           int32_t old_value, int32_t new_value) {
    587   if (kCheckTransaction) {
    588     DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
    589   }
    590   if (kTransactionActive) {
    591     Runtime::Current()->RecordWriteField32(this, field_offset, old_value, true);
    592   }
    593   if (kVerifyFlags & kVerifyThis) {
    594     VerifyObject(this);
    595   }
    596   uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
    597   AtomicInteger* atomic_addr = reinterpret_cast<AtomicInteger*>(raw_addr);
    598 
    599   return atomic_addr->CompareExchangeWeakAcquire(old_value, new_value);
    600 }
    601 
    602 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
    603 inline bool Object::CasFieldWeakRelease32(MemberOffset field_offset,
    604                                           int32_t old_value, int32_t new_value) {
    605   if (kCheckTransaction) {
    606     DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
    607   }
    608   if (kTransactionActive) {
    609     Runtime::Current()->RecordWriteField32(this, field_offset, old_value, true);
    610   }
    611   if (kVerifyFlags & kVerifyThis) {
    612     VerifyObject(this);
    613   }
    614   uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
    615   AtomicInteger* atomic_addr = reinterpret_cast<AtomicInteger*>(raw_addr);
    616 
    617   return atomic_addr->CompareExchangeWeakRelease(old_value, new_value);
    618 }
    619 
    620 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
    621 inline bool Object::CasFieldStrongSequentiallyConsistent32(MemberOffset field_offset,
    622                                                            int32_t old_value, int32_t new_value) {
    623   if (kCheckTransaction) {
    624     DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
    625   }
    626   if (kTransactionActive) {
    627     Runtime::Current()->RecordWriteField32(this, field_offset, old_value, true);
    628   }
    629   if (kVerifyFlags & kVerifyThis) {
    630     VerifyObject(this);
    631   }
    632   uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
    633   AtomicInteger* atomic_addr = reinterpret_cast<AtomicInteger*>(raw_addr);
    634 
    635   return atomic_addr->CompareExchangeStrongSequentiallyConsistent(old_value, new_value);
    636 }
    637 
    638 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags,
    639     bool kIsVolatile>
    640 inline void Object::SetField64(MemberOffset field_offset, int64_t new_value) {
    641   if (kCheckTransaction) {
    642     DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
    643   }
    644   if (kTransactionActive) {
    645     Runtime::Current()->RecordWriteField64(this, field_offset,
    646                                            GetField64<kVerifyFlags, kIsVolatile>(field_offset),
    647                                            kIsVolatile);
    648   }
    649   if (kVerifyFlags & kVerifyThis) {
    650     VerifyObject(this);
    651   }
    652   SetField<int64_t, kIsVolatile>(field_offset, new_value);
    653 }
    654 
    655 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
    656 inline void Object::SetField64Volatile(MemberOffset field_offset, int64_t new_value) {
    657   return SetField64<kTransactionActive, kCheckTransaction, kVerifyFlags, true>(field_offset,
    658                                                                                new_value);
    659 }
    660 
    661 template<typename kSize>
    662 inline kSize Object::GetFieldAcquire(MemberOffset field_offset) {
    663   const uint8_t* raw_addr = reinterpret_cast<const uint8_t*>(this) + field_offset.Int32Value();
    664   const kSize* addr = reinterpret_cast<const kSize*>(raw_addr);
    665   return reinterpret_cast<const Atomic<kSize>*>(addr)->LoadAcquire();
    666 }
    667 
    668 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
    669 inline bool Object::CasFieldWeakSequentiallyConsistent64(MemberOffset field_offset,
    670                                                          int64_t old_value, int64_t new_value) {
    671   if (kCheckTransaction) {
    672     DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
    673   }
    674   if (kTransactionActive) {
    675     Runtime::Current()->RecordWriteField64(this, field_offset, old_value, true);
    676   }
    677   if (kVerifyFlags & kVerifyThis) {
    678     VerifyObject(this);
    679   }
    680   uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
    681   Atomic<int64_t>* atomic_addr = reinterpret_cast<Atomic<int64_t>*>(raw_addr);
    682   return atomic_addr->CompareExchangeWeakSequentiallyConsistent(old_value, new_value);
    683 }
    684 
    685 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
    686 inline bool Object::CasFieldStrongSequentiallyConsistent64(MemberOffset field_offset,
    687                                                            int64_t old_value, int64_t new_value) {
    688   if (kCheckTransaction) {
    689     DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
    690   }
    691   if (kTransactionActive) {
    692     Runtime::Current()->RecordWriteField64(this, field_offset, old_value, true);
    693   }
    694   if (kVerifyFlags & kVerifyThis) {
    695     VerifyObject(this);
    696   }
    697   uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
    698   Atomic<int64_t>* atomic_addr = reinterpret_cast<Atomic<int64_t>*>(raw_addr);
    699   return atomic_addr->CompareExchangeStrongSequentiallyConsistent(old_value, new_value);
    700 }
    701 
    702 template<class T, VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption,
    703          bool kIsVolatile>
    704 inline T* Object::GetFieldObject(MemberOffset field_offset) {
    705   if (kVerifyFlags & kVerifyThis) {
    706     VerifyObject(this);
    707   }
    708   uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
    709   HeapReference<T>* objref_addr = reinterpret_cast<HeapReference<T>*>(raw_addr);
    710   T* result = ReadBarrier::Barrier<T, kReadBarrierOption>(this, field_offset, objref_addr);
    711   if (kIsVolatile) {
    712     // TODO: Refactor to use a SequentiallyConsistent load instead.
    713     QuasiAtomic::ThreadFenceAcquire();  // Ensure visibility of operations preceding store.
    714   }
    715   if (kVerifyFlags & kVerifyReads) {
    716     VerifyObject(result);
    717   }
    718   return result;
    719 }
    720 
    721 template<class T, VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
    722 inline T* Object::GetFieldObjectVolatile(MemberOffset field_offset) {
    723   return GetFieldObject<T, kVerifyFlags, kReadBarrierOption, true>(field_offset);
    724 }
    725 
    726 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags,
    727     bool kIsVolatile>
    728 inline void Object::SetFieldObjectWithoutWriteBarrier(MemberOffset field_offset,
    729                                                       ObjPtr<Object> new_value) {
    730   if (kCheckTransaction) {
    731     DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
    732   }
    733   if (kTransactionActive) {
    734     ObjPtr<Object> obj;
    735     if (kIsVolatile) {
    736       obj = GetFieldObjectVolatile<Object>(field_offset);
    737     } else {
    738       obj = GetFieldObject<Object>(field_offset);
    739     }
    740     Runtime::Current()->RecordWriteFieldReference(this, field_offset, obj.Ptr(), true);
    741   }
    742   if (kVerifyFlags & kVerifyThis) {
    743     VerifyObject(this);
    744   }
    745   if (kVerifyFlags & kVerifyWrites) {
    746     VerifyObject(new_value);
    747   }
    748   uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
    749   HeapReference<Object>* objref_addr = reinterpret_cast<HeapReference<Object>*>(raw_addr);
    750   if (kIsVolatile) {
    751     // TODO: Refactor to use a SequentiallyConsistent store instead.
    752     QuasiAtomic::ThreadFenceRelease();  // Ensure that prior accesses are visible before store.
    753     objref_addr->Assign(new_value.Ptr());
    754     QuasiAtomic::ThreadFenceSequentiallyConsistent();
    755                                 // Ensure this store occurs before any volatile loads.
    756   } else {
    757     objref_addr->Assign(new_value.Ptr());
    758   }
    759 }
    760 
    761 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags,
    762     bool kIsVolatile>
    763 inline void Object::SetFieldObject(MemberOffset field_offset, ObjPtr<Object> new_value) {
    764   SetFieldObjectWithoutWriteBarrier<kTransactionActive, kCheckTransaction, kVerifyFlags,
    765       kIsVolatile>(field_offset, new_value);
    766   if (new_value != nullptr) {
    767     Runtime::Current()->GetHeap()->WriteBarrierField(this, field_offset, new_value);
    768     // TODO: Check field assignment could theoretically cause thread suspension, TODO: fix this.
    769     CheckFieldAssignment(field_offset, new_value);
    770   }
    771 }
    772 
    773 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
    774 inline void Object::SetFieldObjectVolatile(MemberOffset field_offset, ObjPtr<Object> new_value) {
    775   SetFieldObject<kTransactionActive, kCheckTransaction, kVerifyFlags, true>(field_offset,
    776                                                                             new_value);
    777 }
    778 
    779 template <VerifyObjectFlags kVerifyFlags>
    780 inline HeapReference<Object>* Object::GetFieldObjectReferenceAddr(MemberOffset field_offset) {
    781   if (kVerifyFlags & kVerifyThis) {
    782     VerifyObject(this);
    783   }
    784   return reinterpret_cast<HeapReference<Object>*>(reinterpret_cast<uint8_t*>(this) +
    785       field_offset.Int32Value());
    786 }
    787 
    788 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
    789 inline bool Object::CasFieldWeakSequentiallyConsistentObject(MemberOffset field_offset,
    790                                                              ObjPtr<Object> old_value,
    791                                                              ObjPtr<Object> new_value) {
    792   bool success = CasFieldWeakSequentiallyConsistentObjectWithoutWriteBarrier<
    793       kTransactionActive, kCheckTransaction, kVerifyFlags>(field_offset, old_value, new_value);
    794   if (success) {
    795     Runtime::Current()->GetHeap()->WriteBarrierField(this, field_offset, new_value);
    796   }
    797   return success;
    798 }
    799 
    800 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
    801 inline bool Object::CasFieldWeakSequentiallyConsistentObjectWithoutWriteBarrier(
    802     MemberOffset field_offset,
    803     ObjPtr<Object> old_value,
    804     ObjPtr<Object> new_value) {
    805   if (kCheckTransaction) {
    806     DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
    807   }
    808   if (kVerifyFlags & kVerifyThis) {
    809     VerifyObject(this);
    810   }
    811   if (kVerifyFlags & kVerifyWrites) {
    812     VerifyObject(new_value);
    813   }
    814   if (kVerifyFlags & kVerifyReads) {
    815     VerifyObject(old_value);
    816   }
    817   if (kTransactionActive) {
    818     Runtime::Current()->RecordWriteFieldReference(this, field_offset, old_value, true);
    819   }
    820   HeapReference<Object> old_ref(HeapReference<Object>::FromObjPtr(old_value));
    821   HeapReference<Object> new_ref(HeapReference<Object>::FromObjPtr(new_value));
    822   uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
    823   Atomic<uint32_t>* atomic_addr = reinterpret_cast<Atomic<uint32_t>*>(raw_addr);
    824 
    825   bool success = atomic_addr->CompareExchangeWeakSequentiallyConsistent(old_ref.reference_,
    826                                                                         new_ref.reference_);
    827   return success;
    828 }
    829 
    830 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
    831 inline bool Object::CasFieldStrongSequentiallyConsistentObject(MemberOffset field_offset,
    832                                                                ObjPtr<Object> old_value,
    833                                                                ObjPtr<Object> new_value) {
    834   bool success = CasFieldStrongSequentiallyConsistentObjectWithoutWriteBarrier<
    835       kTransactionActive, kCheckTransaction, kVerifyFlags>(field_offset, old_value, new_value);
    836   if (success) {
    837     Runtime::Current()->GetHeap()->WriteBarrierField(this, field_offset, new_value);
    838   }
    839   return success;
    840 }
    841 
    842 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
    843 inline bool Object::CasFieldStrongSequentiallyConsistentObjectWithoutWriteBarrier(
    844     MemberOffset field_offset,
    845     ObjPtr<Object> old_value,
    846     ObjPtr<Object> new_value) {
    847   if (kCheckTransaction) {
    848     DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
    849   }
    850   if (kVerifyFlags & kVerifyThis) {
    851     VerifyObject(this);
    852   }
    853   if (kVerifyFlags & kVerifyWrites) {
    854     VerifyObject(new_value);
    855   }
    856   if (kVerifyFlags & kVerifyReads) {
    857     VerifyObject(old_value);
    858   }
    859   if (kTransactionActive) {
    860     Runtime::Current()->RecordWriteFieldReference(this, field_offset, old_value, true);
    861   }
    862   HeapReference<Object> old_ref(HeapReference<Object>::FromObjPtr(old_value));
    863   HeapReference<Object> new_ref(HeapReference<Object>::FromObjPtr(new_value));
    864   uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
    865   Atomic<uint32_t>* atomic_addr = reinterpret_cast<Atomic<uint32_t>*>(raw_addr);
    866 
    867   bool success = atomic_addr->CompareExchangeStrongSequentiallyConsistent(old_ref.reference_,
    868                                                                           new_ref.reference_);
    869   return success;
    870 }
    871 
    872 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
    873 inline bool Object::CasFieldWeakRelaxedObjectWithoutWriteBarrier(
    874     MemberOffset field_offset,
    875     ObjPtr<Object> old_value,
    876     ObjPtr<Object> new_value) {
    877   if (kCheckTransaction) {
    878     DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
    879   }
    880   if (kVerifyFlags & kVerifyThis) {
    881     VerifyObject(this);
    882   }
    883   if (kVerifyFlags & kVerifyWrites) {
    884     VerifyObject(new_value);
    885   }
    886   if (kVerifyFlags & kVerifyReads) {
    887     VerifyObject(old_value);
    888   }
    889   if (kTransactionActive) {
    890     Runtime::Current()->RecordWriteFieldReference(this, field_offset, old_value, true);
    891   }
    892   HeapReference<Object> old_ref(HeapReference<Object>::FromObjPtr(old_value));
    893   HeapReference<Object> new_ref(HeapReference<Object>::FromObjPtr(new_value));
    894   uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
    895   Atomic<uint32_t>* atomic_addr = reinterpret_cast<Atomic<uint32_t>*>(raw_addr);
    896 
    897   bool success = atomic_addr->CompareExchangeWeakRelaxed(old_ref.reference_,
    898                                                          new_ref.reference_);
    899   return success;
    900 }
    901 
    902 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
    903 inline bool Object::CasFieldWeakReleaseObjectWithoutWriteBarrier(
    904     MemberOffset field_offset,
    905     ObjPtr<Object> old_value,
    906     ObjPtr<Object> new_value) {
    907   if (kCheckTransaction) {
    908     DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
    909   }
    910   if (kVerifyFlags & kVerifyThis) {
    911     VerifyObject(this);
    912   }
    913   if (kVerifyFlags & kVerifyWrites) {
    914     VerifyObject(new_value);
    915   }
    916   if (kVerifyFlags & kVerifyReads) {
    917     VerifyObject(old_value);
    918   }
    919   if (kTransactionActive) {
    920     Runtime::Current()->RecordWriteFieldReference(this, field_offset, old_value, true);
    921   }
    922   HeapReference<Object> old_ref(HeapReference<Object>::FromObjPtr(old_value));
    923   HeapReference<Object> new_ref(HeapReference<Object>::FromObjPtr(new_value));
    924   uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
    925   Atomic<uint32_t>* atomic_addr = reinterpret_cast<Atomic<uint32_t>*>(raw_addr);
    926 
    927   bool success = atomic_addr->CompareExchangeWeakRelease(old_ref.reference_,
    928                                                          new_ref.reference_);
    929   return success;
    930 }
    931 
    932 template<bool kIsStatic,
    933          VerifyObjectFlags kVerifyFlags,
    934          ReadBarrierOption kReadBarrierOption,
    935          typename Visitor>
    936 inline void Object::VisitFieldsReferences(uint32_t ref_offsets, const Visitor& visitor) {
    937   if (!kIsStatic && (ref_offsets != mirror::Class::kClassWalkSuper)) {
    938     // Instance fields and not the slow-path.
    939     uint32_t field_offset = mirror::kObjectHeaderSize;
    940     while (ref_offsets != 0) {
    941       if ((ref_offsets & 1) != 0) {
    942         visitor(this, MemberOffset(field_offset), kIsStatic);
    943       }
    944       ref_offsets >>= 1;
    945       field_offset += sizeof(mirror::HeapReference<mirror::Object>);
    946     }
    947   } else {
    948     // There is no reference offset bitmap. In the non-static case, walk up the class
    949     // inheritance hierarchy and find reference offsets the hard way. In the static case, just
    950     // consider this class.
    951     for (ObjPtr<Class> klass = kIsStatic
    952             ? AsClass<kVerifyFlags, kReadBarrierOption>()
    953             : GetClass<kVerifyFlags, kReadBarrierOption>();
    954         klass != nullptr;
    955         klass = kIsStatic ? nullptr : klass->GetSuperClass<kVerifyFlags, kReadBarrierOption>()) {
    956       const size_t num_reference_fields =
    957           kIsStatic ? klass->NumReferenceStaticFields() : klass->NumReferenceInstanceFields();
    958       if (num_reference_fields == 0u) {
    959         continue;
    960       }
    961       // Presumably GC can happen when we are cross compiling, it should not cause performance
    962       // problems to do pointer size logic.
    963       MemberOffset field_offset = kIsStatic
    964           ? klass->GetFirstReferenceStaticFieldOffset<kVerifyFlags, kReadBarrierOption>(
    965               Runtime::Current()->GetClassLinker()->GetImagePointerSize())
    966           : klass->GetFirstReferenceInstanceFieldOffset<kVerifyFlags, kReadBarrierOption>();
    967       for (size_t i = 0u; i < num_reference_fields; ++i) {
    968         // TODO: Do a simpler check?
    969         if (field_offset.Uint32Value() != ClassOffset().Uint32Value()) {
    970           visitor(this, field_offset, kIsStatic);
    971         }
    972         field_offset = MemberOffset(field_offset.Uint32Value() +
    973                                     sizeof(mirror::HeapReference<mirror::Object>));
    974       }
    975     }
    976   }
    977 }
    978 
    979 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption, typename Visitor>
    980 inline void Object::VisitInstanceFieldsReferences(ObjPtr<Class> klass, const Visitor& visitor) {
    981   VisitFieldsReferences<false, kVerifyFlags, kReadBarrierOption>(
    982       klass->GetReferenceInstanceOffsets<kVerifyFlags>(), visitor);
    983 }
    984 
    985 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption, typename Visitor>
    986 inline void Object::VisitStaticFieldsReferences(ObjPtr<Class> klass, const Visitor& visitor) {
    987   DCHECK(!klass->IsTemp());
    988   klass->VisitFieldsReferences<true, kVerifyFlags, kReadBarrierOption>(0, visitor);
    989 }
    990 
    991 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
    992 inline bool Object::IsClassLoader() {
    993   return GetClass<kVerifyFlags, kReadBarrierOption>()->IsClassLoaderClass();
    994 }
    995 
    996 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
    997 inline mirror::ClassLoader* Object::AsClassLoader() {
    998   DCHECK((IsClassLoader<kVerifyFlags, kReadBarrierOption>()));
    999   return down_cast<mirror::ClassLoader*>(this);
   1000 }
   1001 
   1002 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
   1003 inline bool Object::IsDexCache() {
   1004   return GetClass<kVerifyFlags, kReadBarrierOption>()->IsDexCacheClass();
   1005 }
   1006 
   1007 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
   1008 inline mirror::DexCache* Object::AsDexCache() {
   1009   DCHECK((IsDexCache<kVerifyFlags, kReadBarrierOption>()));
   1010   return down_cast<mirror::DexCache*>(this);
   1011 }
   1012 
   1013 }  // namespace mirror
   1014 }  // namespace art
   1015 
   1016 #endif  // ART_RUNTIME_MIRROR_OBJECT_INL_H_
   1017