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