object-inl.h revision 6a154a419022e2caed4edfd1f311edf733278f35
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 "read_barrier-inl.h" 30#include "runtime.h" 31#include "reference.h" 32#include "throwable.h" 33 34namespace art { 35namespace mirror { 36 37template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption> 38inline Class* Object::GetClass() { 39 return GetFieldObject<Class, kVerifyFlags, kReadBarrierOption>( 40 OFFSET_OF_OBJECT_MEMBER(Object, klass_)); 41} 42 43template<VerifyObjectFlags kVerifyFlags> 44inline void Object::SetClass(Class* new_klass) { 45 // new_klass may be NULL prior to class linker initialization. 46 // We don't mark the card as this occurs as part of object allocation. Not all objects have 47 // backing cards, such as large objects. 48 // We use non transactional version since we can't undo this write. We also disable checking as 49 // we may run in transaction mode here. 50 SetFieldObjectWithoutWriteBarrier<false, false, 51 static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis)>( 52 OFFSET_OF_OBJECT_MEMBER(Object, klass_), new_klass); 53} 54 55inline LockWord Object::GetLockWord(bool as_volatile) { 56 if (as_volatile) { 57 return LockWord(GetField32Volatile(OFFSET_OF_OBJECT_MEMBER(Object, monitor_))); 58 } 59 return LockWord(GetField32(OFFSET_OF_OBJECT_MEMBER(Object, monitor_))); 60} 61 62inline void Object::SetLockWord(LockWord new_val, bool as_volatile) { 63 // Force use of non-transactional mode and do not check. 64 if (as_volatile) { 65 SetField32Volatile<false, false>(OFFSET_OF_OBJECT_MEMBER(Object, monitor_), new_val.GetValue()); 66 } else { 67 SetField32<false, false>(OFFSET_OF_OBJECT_MEMBER(Object, monitor_), new_val.GetValue()); 68 } 69} 70 71inline bool Object::CasLockWord(LockWord old_val, LockWord new_val) { 72 // Force use of non-transactional mode and do not check. 73 return CasField32<false, false>(OFFSET_OF_OBJECT_MEMBER(Object, monitor_), old_val.GetValue(), 74 new_val.GetValue()); 75} 76 77inline uint32_t Object::GetLockOwnerThreadId() { 78 return Monitor::GetLockOwnerThreadId(this); 79} 80 81inline mirror::Object* Object::MonitorEnter(Thread* self) { 82 return Monitor::MonitorEnter(self, this); 83} 84 85inline bool Object::MonitorExit(Thread* self) { 86 return Monitor::MonitorExit(self, this); 87} 88 89inline void Object::Notify(Thread* self) { 90 Monitor::Notify(self, this); 91} 92 93inline void Object::NotifyAll(Thread* self) { 94 Monitor::NotifyAll(self, this); 95} 96 97inline void Object::Wait(Thread* self) { 98 Monitor::Wait(self, this, 0, 0, true, kWaiting); 99} 100 101inline void Object::Wait(Thread* self, int64_t ms, int32_t ns) { 102 Monitor::Wait(self, this, ms, ns, true, kTimedWaiting); 103} 104 105inline Object* Object::GetReadBarrierPointer() { 106#ifdef USE_BAKER_OR_BROOKS_READ_BARRIER 107 DCHECK(kUseBakerOrBrooksReadBarrier); 108 return GetFieldObject<Object, kVerifyNone, kWithoutReadBarrier>( 109 OFFSET_OF_OBJECT_MEMBER(Object, x_rb_ptr_)); 110#else 111 LOG(FATAL) << "Unreachable"; 112 return nullptr; 113#endif 114} 115 116inline void Object::SetReadBarrierPointer(Object* rb_ptr) { 117#ifdef USE_BAKER_OR_BROOKS_READ_BARRIER 118 DCHECK(kUseBakerOrBrooksReadBarrier); 119 // We don't mark the card as this occurs as part of object allocation. Not all objects have 120 // backing cards, such as large objects. 121 SetFieldObjectWithoutWriteBarrier<false, false, kVerifyNone>( 122 OFFSET_OF_OBJECT_MEMBER(Object, x_rb_ptr_), rb_ptr); 123#else 124 LOG(FATAL) << "Unreachable"; 125#endif 126} 127 128inline bool Object::AtomicSetReadBarrierPointer(Object* expected_rb_ptr, Object* rb_ptr) { 129#ifdef USE_BAKER_OR_BROOKS_READ_BARRIER 130 DCHECK(kUseBakerOrBrooksReadBarrier); 131 MemberOffset offset = OFFSET_OF_OBJECT_MEMBER(Object, x_rb_ptr_); 132 byte* raw_addr = reinterpret_cast<byte*>(this) + offset.SizeValue(); 133 HeapReference<Object>* ref = reinterpret_cast<HeapReference<Object>*>(raw_addr); 134 HeapReference<Object> expected_ref(HeapReference<Object>::FromMirrorPtr(expected_rb_ptr)); 135 HeapReference<Object> new_ref(HeapReference<Object>::FromMirrorPtr(rb_ptr)); 136 uint32_t expected_val = expected_ref.reference_; 137 uint32_t new_val; 138 do { 139 uint32_t old_val = ref->reference_; 140 if (old_val != expected_val) { 141 // Lost the race. 142 return false; 143 } 144 new_val = new_ref.reference_; 145 } while (!__sync_bool_compare_and_swap( 146 reinterpret_cast<uint32_t*>(raw_addr), expected_val, new_val)); 147 DCHECK_EQ(new_val, ref->reference_); 148 return true; 149#else 150 LOG(FATAL) << "Unreachable"; 151 return false; 152#endif 153} 154 155inline void Object::AssertReadBarrierPointer() const { 156 if (kUseBakerReadBarrier) { 157 Object* obj = const_cast<Object*>(this); 158 DCHECK(obj->GetReadBarrierPointer() == nullptr) 159 << "Bad Baker pointer: obj=" << reinterpret_cast<void*>(obj) 160 << " ptr=" << reinterpret_cast<void*>(obj->GetReadBarrierPointer()); 161 } else if (kUseBrooksReadBarrier) { 162 Object* obj = const_cast<Object*>(this); 163 DCHECK_EQ(obj, obj->GetReadBarrierPointer()) 164 << "Bad Brooks pointer: obj=" << reinterpret_cast<void*>(obj) 165 << " ptr=" << reinterpret_cast<void*>(obj->GetReadBarrierPointer()); 166 } else { 167 LOG(FATAL) << "Unreachable"; 168 } 169} 170 171template<VerifyObjectFlags kVerifyFlags> 172inline bool Object::VerifierInstanceOf(Class* klass) { 173 DCHECK(klass != NULL); 174 DCHECK(GetClass<kVerifyFlags>() != NULL); 175 return klass->IsInterface() || InstanceOf(klass); 176} 177 178template<VerifyObjectFlags kVerifyFlags> 179inline bool Object::InstanceOf(Class* klass) { 180 DCHECK(klass != NULL); 181 DCHECK(GetClass<kVerifyNone>() != NULL); 182 return klass->IsAssignableFrom(GetClass<kVerifyFlags>()); 183} 184 185template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption> 186inline bool Object::IsClass() { 187 Class* java_lang_Class = GetClass<kVerifyFlags, kReadBarrierOption>()-> 188 template GetClass<kVerifyFlags, kReadBarrierOption>(); 189 return GetClass<static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis), 190 kReadBarrierOption>() == java_lang_Class; 191} 192 193template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption> 194inline Class* Object::AsClass() { 195 DCHECK((IsClass<kVerifyFlags, kReadBarrierOption>())); 196 return down_cast<Class*>(this); 197} 198 199template<VerifyObjectFlags kVerifyFlags> 200inline bool Object::IsObjectArray() { 201 constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis); 202 return IsArrayInstance<kVerifyFlags>() && 203 !GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitive(); 204} 205 206template<class T, VerifyObjectFlags kVerifyFlags> 207inline ObjectArray<T>* Object::AsObjectArray() { 208 DCHECK(IsObjectArray<kVerifyFlags>()); 209 return down_cast<ObjectArray<T>*>(this); 210} 211 212template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption> 213inline bool Object::IsArrayInstance() { 214 return GetClass<kVerifyFlags, kReadBarrierOption>()-> 215 template IsArrayClass<kVerifyFlags, kReadBarrierOption>(); 216} 217 218template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption> 219inline bool Object::IsArtField() { 220 return GetClass<kVerifyFlags, kReadBarrierOption>()-> 221 template IsArtFieldClass<kReadBarrierOption>(); 222} 223 224template<VerifyObjectFlags kVerifyFlags> 225inline ArtField* Object::AsArtField() { 226 DCHECK(IsArtField<kVerifyFlags>()); 227 return down_cast<ArtField*>(this); 228} 229 230template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption> 231inline bool Object::IsArtMethod() { 232 return GetClass<kVerifyFlags, kReadBarrierOption>()-> 233 template IsArtMethodClass<kReadBarrierOption>(); 234} 235 236template<VerifyObjectFlags kVerifyFlags> 237inline ArtMethod* Object::AsArtMethod() { 238 DCHECK(IsArtMethod<kVerifyFlags>()); 239 return down_cast<ArtMethod*>(this); 240} 241 242template<VerifyObjectFlags kVerifyFlags> 243inline bool Object::IsReferenceInstance() { 244 return GetClass<kVerifyFlags>()->IsReferenceClass(); 245} 246 247template<VerifyObjectFlags kVerifyFlags> 248inline Reference* Object::AsReference() { 249 DCHECK(IsReferenceInstance<kVerifyFlags>()); 250 return down_cast<Reference*>(this); 251} 252 253template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption> 254inline Array* Object::AsArray() { 255 DCHECK((IsArrayInstance<kVerifyFlags, kReadBarrierOption>())); 256 return down_cast<Array*>(this); 257} 258 259template<VerifyObjectFlags kVerifyFlags> 260inline BooleanArray* Object::AsBooleanArray() { 261 constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis); 262 DCHECK(GetClass<kVerifyFlags>()->IsArrayClass()); 263 DCHECK(GetClass<kNewFlags>()->GetComponentType()->IsPrimitiveBoolean()); 264 return down_cast<BooleanArray*>(this); 265} 266 267template<VerifyObjectFlags kVerifyFlags> 268inline ByteArray* Object::AsByteArray() { 269 static const VerifyObjectFlags kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis); 270 DCHECK(GetClass<kVerifyFlags>()->IsArrayClass()); 271 DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveByte()); 272 return down_cast<ByteArray*>(this); 273} 274 275template<VerifyObjectFlags kVerifyFlags> 276inline ByteArray* Object::AsByteSizedArray() { 277 constexpr VerifyObjectFlags kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis); 278 DCHECK(GetClass<kVerifyFlags>()->IsArrayClass()); 279 DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveByte() || 280 GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveBoolean()); 281 return down_cast<ByteArray*>(this); 282} 283 284template<VerifyObjectFlags kVerifyFlags> 285inline CharArray* Object::AsCharArray() { 286 constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis); 287 DCHECK(GetClass<kVerifyFlags>()->IsArrayClass()); 288 DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveChar()); 289 return down_cast<CharArray*>(this); 290} 291 292template<VerifyObjectFlags kVerifyFlags> 293inline ShortArray* Object::AsShortArray() { 294 constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis); 295 DCHECK(GetClass<kVerifyFlags>()->IsArrayClass()); 296 DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveShort()); 297 return down_cast<ShortArray*>(this); 298} 299 300template<VerifyObjectFlags kVerifyFlags> 301inline ShortArray* Object::AsShortSizedArray() { 302 constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis); 303 DCHECK(GetClass<kVerifyFlags>()->IsArrayClass()); 304 DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveShort() || 305 GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveChar()); 306 return down_cast<ShortArray*>(this); 307} 308 309template<VerifyObjectFlags kVerifyFlags> 310inline IntArray* Object::AsIntArray() { 311 constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis); 312 DCHECK(GetClass<kVerifyFlags>()->IsArrayClass()); 313 DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveInt() || 314 GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveFloat()); 315 return down_cast<IntArray*>(this); 316} 317 318template<VerifyObjectFlags kVerifyFlags> 319inline LongArray* Object::AsLongArray() { 320 constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis); 321 DCHECK(GetClass<kVerifyFlags>()->IsArrayClass()); 322 DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveLong() || 323 GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveDouble()); 324 return down_cast<LongArray*>(this); 325} 326 327template<VerifyObjectFlags kVerifyFlags> 328inline FloatArray* Object::AsFloatArray() { 329 constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis); 330 DCHECK(GetClass<kVerifyFlags>()->IsArrayClass()); 331 DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveFloat()); 332 return down_cast<FloatArray*>(this); 333} 334 335template<VerifyObjectFlags kVerifyFlags> 336inline DoubleArray* Object::AsDoubleArray() { 337 constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis); 338 DCHECK(GetClass<kVerifyFlags>()->IsArrayClass()); 339 DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveDouble()); 340 return down_cast<DoubleArray*>(this); 341} 342 343template<VerifyObjectFlags kVerifyFlags> 344inline String* Object::AsString() { 345 DCHECK(GetClass<kVerifyFlags>()->IsStringClass()); 346 return down_cast<String*>(this); 347} 348 349template<VerifyObjectFlags kVerifyFlags> 350inline Throwable* Object::AsThrowable() { 351 DCHECK(GetClass<kVerifyFlags>()->IsThrowableClass()); 352 return down_cast<Throwable*>(this); 353} 354 355template<VerifyObjectFlags kVerifyFlags> 356inline bool Object::IsWeakReferenceInstance() { 357 return GetClass<kVerifyFlags>()->IsWeakReferenceClass(); 358} 359 360template<VerifyObjectFlags kVerifyFlags> 361inline bool Object::IsSoftReferenceInstance() { 362 return GetClass<kVerifyFlags>()->IsSoftReferenceClass(); 363} 364 365template<VerifyObjectFlags kVerifyFlags> 366inline bool Object::IsFinalizerReferenceInstance() { 367 return GetClass<kVerifyFlags>()->IsFinalizerReferenceClass(); 368} 369 370template<VerifyObjectFlags kVerifyFlags> 371inline FinalizerReference* Object::AsFinalizerReference() { 372 DCHECK(IsFinalizerReferenceInstance<kVerifyFlags>()); 373 return down_cast<FinalizerReference*>(this); 374} 375 376template<VerifyObjectFlags kVerifyFlags> 377inline bool Object::IsPhantomReferenceInstance() { 378 return GetClass<kVerifyFlags>()->IsPhantomReferenceClass(); 379} 380 381template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption> 382inline size_t Object::SizeOf() { 383 size_t result; 384 constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis); 385 if (IsArrayInstance<kVerifyFlags, kReadBarrierOption>()) { 386 result = AsArray<kNewFlags, kReadBarrierOption>()-> 387 template SizeOf<kNewFlags, kReadBarrierOption>(); 388 } else if (IsClass<kNewFlags, kReadBarrierOption>()) { 389 result = AsClass<kNewFlags, kReadBarrierOption>()-> 390 template SizeOf<kNewFlags, kReadBarrierOption>(); 391 } else { 392 result = GetClass<kNewFlags, kReadBarrierOption>()->GetObjectSize(); 393 } 394 DCHECK_GE(result, sizeof(Object)) 395 << " class=" << PrettyTypeOf(GetClass<kNewFlags, kReadBarrierOption>()); 396 DCHECK(!(IsArtField<kNewFlags, kReadBarrierOption>()) || result == sizeof(ArtField)); 397 DCHECK(!(IsArtMethod<kNewFlags, kReadBarrierOption>()) || result == sizeof(ArtMethod)); 398 return result; 399} 400 401template<VerifyObjectFlags kVerifyFlags, bool kIsVolatile> 402inline int32_t Object::GetField32(MemberOffset field_offset) { 403 if (kVerifyFlags & kVerifyThis) { 404 VerifyObject(this); 405 } 406 const byte* raw_addr = reinterpret_cast<const byte*>(this) + field_offset.Int32Value(); 407 const int32_t* word_addr = reinterpret_cast<const int32_t*>(raw_addr); 408 if (UNLIKELY(kIsVolatile)) { 409 int32_t result = *(reinterpret_cast<volatile int32_t*>(const_cast<int32_t*>(word_addr))); 410 QuasiAtomic::MembarLoadLoad(); // Ensure volatile loads don't re-order. 411 return result; 412 } else { 413 return *word_addr; 414 } 415} 416 417template<VerifyObjectFlags kVerifyFlags> 418inline int32_t Object::GetField32Volatile(MemberOffset field_offset) { 419 return GetField32<kVerifyFlags, true>(field_offset); 420} 421 422template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags, 423 bool kIsVolatile> 424inline void Object::SetField32(MemberOffset field_offset, int32_t new_value) { 425 if (kCheckTransaction) { 426 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction()); 427 } 428 if (kTransactionActive) { 429 Runtime::Current()->RecordWriteField32(this, field_offset, 430 GetField32<kVerifyFlags, kIsVolatile>(field_offset), 431 kIsVolatile); 432 } 433 if (kVerifyFlags & kVerifyThis) { 434 VerifyObject(this); 435 } 436 byte* raw_addr = reinterpret_cast<byte*>(this) + field_offset.Int32Value(); 437 int32_t* word_addr = reinterpret_cast<int32_t*>(raw_addr); 438 if (kIsVolatile) { 439 QuasiAtomic::MembarStoreStore(); // Ensure this store occurs after others in the queue. 440 *word_addr = new_value; 441 QuasiAtomic::MembarStoreLoad(); // Ensure this store occurs before any volatile loads. 442 } else { 443 *word_addr = new_value; 444 } 445} 446 447template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> 448inline void Object::SetField32Volatile(MemberOffset field_offset, int32_t new_value) { 449 SetField32<kTransactionActive, kCheckTransaction, kVerifyFlags, true>(field_offset, new_value); 450} 451 452template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> 453inline bool Object::CasField32(MemberOffset field_offset, int32_t old_value, int32_t new_value) { 454 if (kCheckTransaction) { 455 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction()); 456 } 457 if (kTransactionActive) { 458 Runtime::Current()->RecordWriteField32(this, field_offset, old_value, true); 459 } 460 if (kVerifyFlags & kVerifyThis) { 461 VerifyObject(this); 462 } 463 byte* raw_addr = reinterpret_cast<byte*>(this) + field_offset.Int32Value(); 464 volatile int32_t* addr = reinterpret_cast<volatile int32_t*>(raw_addr); 465 return __sync_bool_compare_and_swap(addr, old_value, new_value); 466} 467 468template<VerifyObjectFlags kVerifyFlags, bool kIsVolatile> 469inline int64_t Object::GetField64(MemberOffset field_offset) { 470 if (kVerifyFlags & kVerifyThis) { 471 VerifyObject(this); 472 } 473 const byte* raw_addr = reinterpret_cast<const byte*>(this) + field_offset.Int32Value(); 474 const int64_t* addr = reinterpret_cast<const int64_t*>(raw_addr); 475 if (kIsVolatile) { 476 int64_t result = QuasiAtomic::Read64(addr); 477 QuasiAtomic::MembarLoadLoad(); // Ensure volatile loads don't re-order. 478 return result; 479 } else { 480 return *addr; 481 } 482} 483 484template<VerifyObjectFlags kVerifyFlags> 485inline int64_t Object::GetField64Volatile(MemberOffset field_offset) { 486 return GetField64<kVerifyFlags, true>(field_offset); 487} 488 489template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags, 490 bool kIsVolatile> 491inline void Object::SetField64(MemberOffset field_offset, int64_t new_value) { 492 if (kCheckTransaction) { 493 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction()); 494 } 495 if (kTransactionActive) { 496 Runtime::Current()->RecordWriteField64(this, field_offset, 497 GetField64<kVerifyFlags, kIsVolatile>(field_offset), 498 kIsVolatile); 499 } 500 if (kVerifyFlags & kVerifyThis) { 501 VerifyObject(this); 502 } 503 byte* raw_addr = reinterpret_cast<byte*>(this) + field_offset.Int32Value(); 504 int64_t* addr = reinterpret_cast<int64_t*>(raw_addr); 505 if (kIsVolatile) { 506 QuasiAtomic::MembarStoreStore(); // Ensure this store occurs after others in the queue. 507 QuasiAtomic::Write64(addr, new_value); 508 if (!QuasiAtomic::LongAtomicsUseMutexes()) { 509 QuasiAtomic::MembarStoreLoad(); // Ensure this store occurs before any volatile loads. 510 } else { 511 // Fence from from mutex is enough. 512 } 513 } else { 514 *addr = new_value; 515 } 516} 517 518template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> 519inline void Object::SetField64Volatile(MemberOffset field_offset, int64_t new_value) { 520 return SetField64<kTransactionActive, kCheckTransaction, kVerifyFlags, true>(field_offset, 521 new_value); 522} 523 524template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> 525inline bool Object::CasField64(MemberOffset field_offset, int64_t old_value, int64_t new_value) { 526 if (kCheckTransaction) { 527 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction()); 528 } 529 if (kTransactionActive) { 530 Runtime::Current()->RecordWriteField64(this, field_offset, old_value, true); 531 } 532 if (kVerifyFlags & kVerifyThis) { 533 VerifyObject(this); 534 } 535 byte* raw_addr = reinterpret_cast<byte*>(this) + field_offset.Int32Value(); 536 volatile int64_t* addr = reinterpret_cast<volatile int64_t*>(raw_addr); 537 return QuasiAtomic::Cas64(old_value, new_value, addr); 538} 539 540template<class T, VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption, 541 bool kIsVolatile> 542inline T* Object::GetFieldObject(MemberOffset field_offset) { 543 if (kVerifyFlags & kVerifyThis) { 544 VerifyObject(this); 545 } 546 byte* raw_addr = reinterpret_cast<byte*>(this) + field_offset.Int32Value(); 547 HeapReference<T>* objref_addr = reinterpret_cast<HeapReference<T>*>(raw_addr); 548 T* result = ReadBarrier::Barrier<T, kReadBarrierOption>(this, field_offset, objref_addr); 549 if (kIsVolatile) { 550 QuasiAtomic::MembarLoadLoad(); // Ensure loads don't re-order. 551 } 552 if (kVerifyFlags & kVerifyReads) { 553 VerifyObject(result); 554 } 555 return result; 556} 557 558template<class T, VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption> 559inline T* Object::GetFieldObjectVolatile(MemberOffset field_offset) { 560 return GetFieldObject<T, kVerifyFlags, kReadBarrierOption, true>(field_offset); 561} 562 563template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags, 564 bool kIsVolatile> 565inline void Object::SetFieldObjectWithoutWriteBarrier(MemberOffset field_offset, 566 Object* new_value) { 567 if (kCheckTransaction) { 568 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction()); 569 } 570 if (kTransactionActive) { 571 mirror::Object* obj; 572 if (kIsVolatile) { 573 obj = GetFieldObjectVolatile<Object>(field_offset); 574 } else { 575 obj = GetFieldObject<Object>(field_offset); 576 } 577 Runtime::Current()->RecordWriteFieldReference(this, field_offset, obj, true); 578 } 579 if (kVerifyFlags & kVerifyThis) { 580 VerifyObject(this); 581 } 582 if (kVerifyFlags & kVerifyWrites) { 583 VerifyObject(new_value); 584 } 585 byte* raw_addr = reinterpret_cast<byte*>(this) + field_offset.Int32Value(); 586 HeapReference<Object>* objref_addr = reinterpret_cast<HeapReference<Object>*>(raw_addr); 587 if (kIsVolatile) { 588 QuasiAtomic::MembarStoreStore(); // Ensure this store occurs after others in the queue. 589 objref_addr->Assign(new_value); 590 QuasiAtomic::MembarStoreLoad(); // Ensure this store occurs before any loads. 591 } else { 592 objref_addr->Assign(new_value); 593 } 594} 595 596template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags, 597 bool kIsVolatile> 598inline void Object::SetFieldObject(MemberOffset field_offset, Object* new_value) { 599 SetFieldObjectWithoutWriteBarrier<kTransactionActive, kCheckTransaction, kVerifyFlags, 600 kIsVolatile>(field_offset, new_value); 601 if (new_value != nullptr) { 602 CheckFieldAssignment(field_offset, new_value); 603 Runtime::Current()->GetHeap()->WriteBarrierField(this, field_offset, new_value); 604 } 605} 606 607template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> 608inline void Object::SetFieldObjectVolatile(MemberOffset field_offset, Object* new_value) { 609 SetFieldObject<kTransactionActive, kCheckTransaction, kVerifyFlags, true>(field_offset, 610 new_value); 611} 612 613template <VerifyObjectFlags kVerifyFlags> 614inline HeapReference<Object>* Object::GetFieldObjectReferenceAddr(MemberOffset field_offset) { 615 if (kVerifyFlags & kVerifyThis) { 616 VerifyObject(this); 617 } 618 return reinterpret_cast<HeapReference<Object>*>(reinterpret_cast<byte*>(this) + 619 field_offset.Int32Value()); 620} 621 622template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> 623inline bool Object::CasFieldObject(MemberOffset field_offset, Object* old_value, 624 Object* new_value) { 625 if (kCheckTransaction) { 626 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction()); 627 } 628 if (kVerifyFlags & kVerifyThis) { 629 VerifyObject(this); 630 } 631 if (kVerifyFlags & kVerifyWrites) { 632 VerifyObject(new_value); 633 } 634 if (kVerifyFlags & kVerifyReads) { 635 VerifyObject(old_value); 636 } 637 if (kTransactionActive) { 638 Runtime::Current()->RecordWriteFieldReference(this, field_offset, old_value, true); 639 } 640 byte* raw_addr = reinterpret_cast<byte*>(this) + field_offset.Int32Value(); 641 volatile int32_t* addr = reinterpret_cast<volatile int32_t*>(raw_addr); 642 HeapReference<Object> old_ref(HeapReference<Object>::FromMirrorPtr(old_value)); 643 HeapReference<Object> new_ref(HeapReference<Object>::FromMirrorPtr(new_value)); 644 bool success = __sync_bool_compare_and_swap(addr, old_ref.reference_, new_ref.reference_); 645 if (success) { 646 Runtime::Current()->GetHeap()->WriteBarrierField(this, field_offset, new_value); 647 } 648 return success; 649} 650 651template<bool kVisitClass, bool kIsStatic, typename Visitor> 652inline void Object::VisitFieldsReferences(uint32_t ref_offsets, const Visitor& visitor) { 653 if (LIKELY(ref_offsets != CLASS_WALK_SUPER)) { 654 if (!kVisitClass) { 655 // Mask out the class from the reference offsets. 656 ref_offsets ^= kWordHighBitMask; 657 } 658 DCHECK_EQ(ClassOffset().Uint32Value(), 0U); 659 // Found a reference offset bitmap. Visit the specified offsets. 660 while (ref_offsets != 0) { 661 size_t right_shift = CLZ(ref_offsets); 662 MemberOffset field_offset = CLASS_OFFSET_FROM_CLZ(right_shift); 663 visitor(this, field_offset, kIsStatic); 664 ref_offsets &= ~(CLASS_HIGH_BIT >> right_shift); 665 } 666 } else { 667 // There is no reference offset bitmap. In the non-static case, walk up the class 668 // inheritance hierarchy and find reference offsets the hard way. In the static case, just 669 // consider this class. 670 for (mirror::Class* klass = kIsStatic ? AsClass() : GetClass(); klass != nullptr; 671 klass = kIsStatic ? nullptr : klass->GetSuperClass()) { 672 size_t num_reference_fields = 673 kIsStatic ? klass->NumReferenceStaticFields() : klass->NumReferenceInstanceFields(); 674 for (size_t i = 0; i < num_reference_fields; ++i) { 675 mirror::ArtField* field = kIsStatic ? klass->GetStaticField(i) : klass->GetInstanceField(i); 676 MemberOffset field_offset = field->GetOffset(); 677 // TODO: Do a simpler check? 678 if (!kVisitClass && UNLIKELY(field_offset.Uint32Value() == ClassOffset().Uint32Value())) { 679 continue; 680 } 681 visitor(this, field_offset, kIsStatic); 682 } 683 } 684 } 685} 686 687template<bool kVisitClass, typename Visitor> 688inline void Object::VisitInstanceFieldsReferences(mirror::Class* klass, const Visitor& visitor) { 689 VisitFieldsReferences<kVisitClass, false>( 690 klass->GetReferenceInstanceOffsets<kVerifyNone>(), visitor); 691} 692 693template<bool kVisitClass, typename Visitor> 694inline void Object::VisitStaticFieldsReferences(mirror::Class* klass, const Visitor& visitor) { 695 klass->VisitFieldsReferences<kVisitClass, true>( 696 klass->GetReferenceStaticOffsets<kVerifyNone>(), visitor); 697} 698 699template <const bool kVisitClass, VerifyObjectFlags kVerifyFlags, typename Visitor, 700 typename JavaLangRefVisitor> 701inline void Object::VisitReferences(const Visitor& visitor, 702 const JavaLangRefVisitor& ref_visitor) { 703 mirror::Class* klass = GetClass<kVerifyFlags>(); 704 if (klass->IsVariableSize()) { 705 if (klass->IsClassClass()) { 706 AsClass<kVerifyNone>()->VisitReferences<kVisitClass>(klass, visitor); 707 } else { 708 DCHECK(klass->IsArrayClass<kVerifyFlags>()); 709 if (klass->IsObjectArrayClass<kVerifyNone>()) { 710 AsObjectArray<mirror::Object, kVerifyNone>()->VisitReferences<kVisitClass>(visitor); 711 } else if (kVisitClass) { 712 visitor(this, ClassOffset(), false); 713 } 714 } 715 } else { 716 VisitInstanceFieldsReferences<kVisitClass>(klass, visitor); 717 if (UNLIKELY(klass->IsReferenceClass<kVerifyNone>())) { 718 ref_visitor(klass, AsReference()); 719 } 720 } 721} 722 723} // namespace mirror 724} // namespace art 725 726#endif // ART_RUNTIME_MIRROR_OBJECT_INL_H_ 727