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