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