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