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