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