object-inl.h revision 61c5ebc6aee2cac1c363de6fbdac25ada1697fdb
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>()->IsArtFieldClass(); 221} 222 223template<VerifyObjectFlags kVerifyFlags> 224inline ArtField* Object::AsArtField() { 225 DCHECK(IsArtField<kVerifyFlags>()); 226 return down_cast<ArtField*>(this); 227} 228 229template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption> 230inline bool Object::IsArtMethod() { 231 return GetClass<kVerifyFlags, kReadBarrierOption>()->IsArtMethodClass(); 232} 233 234template<VerifyObjectFlags kVerifyFlags> 235inline ArtMethod* Object::AsArtMethod() { 236 DCHECK(IsArtMethod<kVerifyFlags>()); 237 return down_cast<ArtMethod*>(this); 238} 239 240template<VerifyObjectFlags kVerifyFlags> 241inline bool Object::IsReferenceInstance() { 242 return GetClass<kVerifyFlags>()->IsReferenceClass(); 243} 244 245template<VerifyObjectFlags kVerifyFlags> 246inline Reference* Object::AsReference() { 247 DCHECK(IsReferenceInstance<kVerifyFlags>()); 248 return down_cast<Reference*>(this); 249} 250 251template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption> 252inline Array* Object::AsArray() { 253 DCHECK((IsArrayInstance<kVerifyFlags, kReadBarrierOption>())); 254 return down_cast<Array*>(this); 255} 256 257template<VerifyObjectFlags kVerifyFlags> 258inline BooleanArray* Object::AsBooleanArray() { 259 constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis); 260 DCHECK(GetClass<kVerifyFlags>()->IsArrayClass()); 261 DCHECK(GetClass<kNewFlags>()->GetComponentType()->IsPrimitiveBoolean()); 262 return down_cast<BooleanArray*>(this); 263} 264 265template<VerifyObjectFlags kVerifyFlags> 266inline ByteArray* Object::AsByteArray() { 267 static const VerifyObjectFlags kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis); 268 DCHECK(GetClass<kVerifyFlags>()->IsArrayClass()); 269 DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveByte()); 270 return down_cast<ByteArray*>(this); 271} 272 273template<VerifyObjectFlags kVerifyFlags> 274inline ByteArray* Object::AsByteSizedArray() { 275 constexpr VerifyObjectFlags kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis); 276 DCHECK(GetClass<kVerifyFlags>()->IsArrayClass()); 277 DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveByte() || 278 GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveBoolean()); 279 return down_cast<ByteArray*>(this); 280} 281 282template<VerifyObjectFlags kVerifyFlags> 283inline CharArray* Object::AsCharArray() { 284 constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis); 285 DCHECK(GetClass<kVerifyFlags>()->IsArrayClass()); 286 DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveChar()); 287 return down_cast<CharArray*>(this); 288} 289 290template<VerifyObjectFlags kVerifyFlags> 291inline ShortArray* Object::AsShortArray() { 292 constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis); 293 DCHECK(GetClass<kVerifyFlags>()->IsArrayClass()); 294 DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveShort()); 295 return down_cast<ShortArray*>(this); 296} 297 298template<VerifyObjectFlags kVerifyFlags> 299inline ShortArray* Object::AsShortSizedArray() { 300 constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis); 301 DCHECK(GetClass<kVerifyFlags>()->IsArrayClass()); 302 DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveShort() || 303 GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveChar()); 304 return down_cast<ShortArray*>(this); 305} 306 307template<VerifyObjectFlags kVerifyFlags> 308inline IntArray* Object::AsIntArray() { 309 constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis); 310 DCHECK(GetClass<kVerifyFlags>()->IsArrayClass()); 311 DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveInt() || 312 GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveFloat()); 313 return down_cast<IntArray*>(this); 314} 315 316template<VerifyObjectFlags kVerifyFlags> 317inline LongArray* Object::AsLongArray() { 318 constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis); 319 DCHECK(GetClass<kVerifyFlags>()->IsArrayClass()); 320 DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveLong() || 321 GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveDouble()); 322 return down_cast<LongArray*>(this); 323} 324 325template<VerifyObjectFlags kVerifyFlags> 326inline FloatArray* Object::AsFloatArray() { 327 constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis); 328 DCHECK(GetClass<kVerifyFlags>()->IsArrayClass()); 329 DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveFloat()); 330 return down_cast<FloatArray*>(this); 331} 332 333template<VerifyObjectFlags kVerifyFlags> 334inline DoubleArray* Object::AsDoubleArray() { 335 constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis); 336 DCHECK(GetClass<kVerifyFlags>()->IsArrayClass()); 337 DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveDouble()); 338 return down_cast<DoubleArray*>(this); 339} 340 341template<VerifyObjectFlags kVerifyFlags> 342inline String* Object::AsString() { 343 DCHECK(GetClass<kVerifyFlags>()->IsStringClass()); 344 return down_cast<String*>(this); 345} 346 347template<VerifyObjectFlags kVerifyFlags> 348inline Throwable* Object::AsThrowable() { 349 DCHECK(GetClass<kVerifyFlags>()->IsThrowableClass()); 350 return down_cast<Throwable*>(this); 351} 352 353template<VerifyObjectFlags kVerifyFlags> 354inline bool Object::IsWeakReferenceInstance() { 355 return GetClass<kVerifyFlags>()->IsWeakReferenceClass(); 356} 357 358template<VerifyObjectFlags kVerifyFlags> 359inline bool Object::IsSoftReferenceInstance() { 360 return GetClass<kVerifyFlags>()->IsSoftReferenceClass(); 361} 362 363template<VerifyObjectFlags kVerifyFlags> 364inline bool Object::IsFinalizerReferenceInstance() { 365 return GetClass<kVerifyFlags>()->IsFinalizerReferenceClass(); 366} 367 368template<VerifyObjectFlags kVerifyFlags> 369inline FinalizerReference* Object::AsFinalizerReference() { 370 DCHECK(IsFinalizerReferenceInstance<kVerifyFlags>()); 371 return down_cast<FinalizerReference*>(this); 372} 373 374template<VerifyObjectFlags kVerifyFlags> 375inline bool Object::IsPhantomReferenceInstance() { 376 return GetClass<kVerifyFlags>()->IsPhantomReferenceClass(); 377} 378 379template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption> 380inline size_t Object::SizeOf() { 381 size_t result; 382 constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis); 383 if (IsArrayInstance<kVerifyFlags, kReadBarrierOption>()) { 384 result = AsArray<kNewFlags, kReadBarrierOption>()-> 385 template SizeOf<kNewFlags, kReadBarrierOption>(); 386 } else if (IsClass<kNewFlags, kReadBarrierOption>()) { 387 result = AsClass<kNewFlags, kReadBarrierOption>()-> 388 template SizeOf<kNewFlags, kReadBarrierOption>(); 389 } else { 390 result = GetClass<kNewFlags, kReadBarrierOption>()-> 391 template GetObjectSize<kNewFlags, kReadBarrierOption>(); 392 } 393 DCHECK_GE(result, sizeof(Object)) 394 << " class=" << PrettyTypeOf(GetClass<kNewFlags, kReadBarrierOption>()); 395 DCHECK(!(IsArtField<kNewFlags, kReadBarrierOption>()) || result == sizeof(ArtField)); 396 DCHECK(!(IsArtMethod<kNewFlags, kReadBarrierOption>()) || result == sizeof(ArtMethod)); 397 return result; 398} 399 400template<VerifyObjectFlags kVerifyFlags, bool kIsVolatile> 401inline int32_t Object::GetField32(MemberOffset field_offset) { 402 if (kVerifyFlags & kVerifyThis) { 403 VerifyObject(this); 404 } 405 const byte* raw_addr = reinterpret_cast<const byte*>(this) + field_offset.Int32Value(); 406 const int32_t* word_addr = reinterpret_cast<const int32_t*>(raw_addr); 407 if (UNLIKELY(kIsVolatile)) { 408 int32_t result = *(reinterpret_cast<volatile int32_t*>(const_cast<int32_t*>(word_addr))); 409 QuasiAtomic::MembarLoadLoad(); // Ensure volatile loads don't re-order. 410 return result; 411 } else { 412 return *word_addr; 413 } 414} 415 416template<VerifyObjectFlags kVerifyFlags> 417inline int32_t Object::GetField32Volatile(MemberOffset field_offset) { 418 return GetField32<kVerifyFlags, true>(field_offset); 419} 420 421template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags, 422 bool kIsVolatile> 423inline void Object::SetField32(MemberOffset field_offset, int32_t new_value) { 424 if (kCheckTransaction) { 425 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction()); 426 } 427 if (kTransactionActive) { 428 Runtime::Current()->RecordWriteField32(this, field_offset, 429 GetField32<kVerifyFlags, kIsVolatile>(field_offset), 430 kIsVolatile); 431 } 432 if (kVerifyFlags & kVerifyThis) { 433 VerifyObject(this); 434 } 435 byte* raw_addr = reinterpret_cast<byte*>(this) + field_offset.Int32Value(); 436 int32_t* word_addr = reinterpret_cast<int32_t*>(raw_addr); 437 if (kIsVolatile) { 438 QuasiAtomic::MembarStoreStore(); // Ensure this store occurs after others in the queue. 439 *word_addr = new_value; 440 QuasiAtomic::MembarStoreLoad(); // Ensure this store occurs before any volatile loads. 441 } else { 442 *word_addr = new_value; 443 } 444} 445 446template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> 447inline void Object::SetField32Volatile(MemberOffset field_offset, int32_t new_value) { 448 SetField32<kTransactionActive, kCheckTransaction, kVerifyFlags, true>(field_offset, new_value); 449} 450 451template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> 452inline bool Object::CasField32(MemberOffset field_offset, int32_t old_value, int32_t new_value) { 453 if (kCheckTransaction) { 454 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction()); 455 } 456 if (kTransactionActive) { 457 Runtime::Current()->RecordWriteField32(this, field_offset, old_value, true); 458 } 459 if (kVerifyFlags & kVerifyThis) { 460 VerifyObject(this); 461 } 462 byte* raw_addr = reinterpret_cast<byte*>(this) + field_offset.Int32Value(); 463 volatile int32_t* addr = reinterpret_cast<volatile int32_t*>(raw_addr); 464 return __sync_bool_compare_and_swap(addr, old_value, new_value); 465} 466 467template<VerifyObjectFlags kVerifyFlags, bool kIsVolatile> 468inline int64_t Object::GetField64(MemberOffset field_offset) { 469 if (kVerifyFlags & kVerifyThis) { 470 VerifyObject(this); 471 } 472 const byte* raw_addr = reinterpret_cast<const byte*>(this) + field_offset.Int32Value(); 473 const int64_t* addr = reinterpret_cast<const int64_t*>(raw_addr); 474 if (kIsVolatile) { 475 int64_t result = QuasiAtomic::Read64(addr); 476 QuasiAtomic::MembarLoadLoad(); // Ensure volatile loads don't re-order. 477 return result; 478 } else { 479 return *addr; 480 } 481} 482 483template<VerifyObjectFlags kVerifyFlags> 484inline int64_t Object::GetField64Volatile(MemberOffset field_offset) { 485 return GetField64<kVerifyFlags, true>(field_offset); 486} 487 488template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags, 489 bool kIsVolatile> 490inline void Object::SetField64(MemberOffset field_offset, int64_t new_value) { 491 if (kCheckTransaction) { 492 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction()); 493 } 494 if (kTransactionActive) { 495 Runtime::Current()->RecordWriteField64(this, field_offset, 496 GetField64<kVerifyFlags, kIsVolatile>(field_offset), 497 kIsVolatile); 498 } 499 if (kVerifyFlags & kVerifyThis) { 500 VerifyObject(this); 501 } 502 byte* raw_addr = reinterpret_cast<byte*>(this) + field_offset.Int32Value(); 503 int64_t* addr = reinterpret_cast<int64_t*>(raw_addr); 504 if (kIsVolatile) { 505 QuasiAtomic::MembarStoreStore(); // Ensure this store occurs after others in the queue. 506 QuasiAtomic::Write64(addr, new_value); 507 if (!QuasiAtomic::LongAtomicsUseMutexes()) { 508 QuasiAtomic::MembarStoreLoad(); // Ensure this store occurs before any volatile loads. 509 } else { 510 // Fence from from mutex is enough. 511 } 512 } else { 513 *addr = new_value; 514 } 515} 516 517template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> 518inline void Object::SetField64Volatile(MemberOffset field_offset, int64_t new_value) { 519 return SetField64<kTransactionActive, kCheckTransaction, kVerifyFlags, true>(field_offset, 520 new_value); 521} 522 523template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> 524inline bool Object::CasField64(MemberOffset field_offset, int64_t old_value, int64_t new_value) { 525 if (kCheckTransaction) { 526 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction()); 527 } 528 if (kTransactionActive) { 529 Runtime::Current()->RecordWriteField64(this, field_offset, old_value, true); 530 } 531 if (kVerifyFlags & kVerifyThis) { 532 VerifyObject(this); 533 } 534 byte* raw_addr = reinterpret_cast<byte*>(this) + field_offset.Int32Value(); 535 volatile int64_t* addr = reinterpret_cast<volatile int64_t*>(raw_addr); 536 return QuasiAtomic::Cas64(old_value, new_value, addr); 537} 538 539template<class T, VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption, 540 bool kIsVolatile> 541inline T* Object::GetFieldObject(MemberOffset field_offset) { 542 if (kVerifyFlags & kVerifyThis) { 543 VerifyObject(this); 544 } 545 byte* raw_addr = reinterpret_cast<byte*>(this) + field_offset.Int32Value(); 546 HeapReference<T>* objref_addr = reinterpret_cast<HeapReference<T>*>(raw_addr); 547 T* result = ReadBarrier::Barrier<T, kReadBarrierOption>(this, field_offset, objref_addr); 548 if (kIsVolatile) { 549 QuasiAtomic::MembarLoadLoad(); // Ensure loads don't re-order. 550 } 551 if (kVerifyFlags & kVerifyReads) { 552 VerifyObject(result); 553 } 554 return result; 555} 556 557template<class T, VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption> 558inline T* Object::GetFieldObjectVolatile(MemberOffset field_offset) { 559 return GetFieldObject<T, kVerifyFlags, kReadBarrierOption, true>(field_offset); 560} 561 562template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags, 563 bool kIsVolatile> 564inline void Object::SetFieldObjectWithoutWriteBarrier(MemberOffset field_offset, 565 Object* new_value) { 566 if (kCheckTransaction) { 567 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction()); 568 } 569 if (kTransactionActive) { 570 mirror::Object* obj; 571 if (kIsVolatile) { 572 obj = GetFieldObjectVolatile<Object>(field_offset); 573 } else { 574 obj = GetFieldObject<Object>(field_offset); 575 } 576 Runtime::Current()->RecordWriteFieldReference(this, field_offset, obj, true); 577 } 578 if (kVerifyFlags & kVerifyThis) { 579 VerifyObject(this); 580 } 581 if (kVerifyFlags & kVerifyWrites) { 582 VerifyObject(new_value); 583 } 584 byte* raw_addr = reinterpret_cast<byte*>(this) + field_offset.Int32Value(); 585 HeapReference<Object>* objref_addr = reinterpret_cast<HeapReference<Object>*>(raw_addr); 586 if (kIsVolatile) { 587 QuasiAtomic::MembarStoreStore(); // Ensure this store occurs after others in the queue. 588 objref_addr->Assign(new_value); 589 QuasiAtomic::MembarStoreLoad(); // Ensure this store occurs before any loads. 590 } else { 591 objref_addr->Assign(new_value); 592 } 593} 594 595template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags, 596 bool kIsVolatile> 597inline void Object::SetFieldObject(MemberOffset field_offset, Object* new_value) { 598 SetFieldObjectWithoutWriteBarrier<kTransactionActive, kCheckTransaction, kVerifyFlags, 599 kIsVolatile>(field_offset, new_value); 600 if (new_value != nullptr) { 601 Runtime::Current()->GetHeap()->WriteBarrierField(this, field_offset, new_value); 602 // TODO: Check field assignment could theoretically cause thread suspension, TODO: fix this. 603 CheckFieldAssignment(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