object-inl.h revision 5abc6f913bc77aa3b9c05ad07905d4c1c28b2661
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 return result; 407} 408 409template<VerifyObjectFlags kVerifyFlags, bool kIsVolatile> 410inline int8_t Object::GetField8(MemberOffset field_offset) { 411 if (kVerifyFlags & kVerifyThis) { 412 VerifyObject(this); 413 } 414 const byte* raw_addr = reinterpret_cast<const byte*>(this) + field_offset.Int32Value(); 415 const int8_t* word_addr = reinterpret_cast<const int8_t*>(raw_addr); 416 if (UNLIKELY(kIsVolatile)) { 417 return reinterpret_cast<const Atomic<int8_t>*>(word_addr)->LoadSequentiallyConsistent(); 418 } else { 419 return reinterpret_cast<const Atomic<int8_t>*>(word_addr)->LoadJavaData(); 420 } 421} 422 423template<bool kCheckTransaction, VerifyObjectFlags kVerifyFlags, 424 bool kIsVolatile> 425inline void Object::SetField8(MemberOffset field_offset, int8_t new_value) { 426 if (kCheckTransaction) { 427 DCHECK_EQ(false, Runtime::Current()->IsActiveTransaction()); 428 } 429 if (kVerifyFlags & kVerifyThis) { 430 VerifyObject(this); 431 } 432 byte* raw_addr = reinterpret_cast<byte*>(this) + field_offset.Int32Value(); 433 int8_t* word_addr = reinterpret_cast<int8_t*>(raw_addr); 434 if (kIsVolatile) { 435 reinterpret_cast<Atomic<int8_t>*>(word_addr)->StoreSequentiallyConsistent(new_value); 436 } else { 437 reinterpret_cast<Atomic<int8_t>*>(word_addr)->StoreJavaData(new_value); 438 } 439} 440 441template<VerifyObjectFlags kVerifyFlags, bool kIsVolatile> 442inline int16_t Object::GetField16(MemberOffset field_offset) { 443 if (kVerifyFlags & kVerifyThis) { 444 VerifyObject(this); 445 } 446 const byte* raw_addr = reinterpret_cast<const byte*>(this) + field_offset.Int32Value(); 447 const int16_t* word_addr = reinterpret_cast<const int16_t*>(raw_addr); 448 if (UNLIKELY(kIsVolatile)) { 449 return reinterpret_cast<const Atomic<int16_t>*>(word_addr)->LoadSequentiallyConsistent(); 450 } else { 451 return reinterpret_cast<const Atomic<int16_t>*>(word_addr)->LoadJavaData(); 452 } 453} 454 455template<bool kCheckTransaction, VerifyObjectFlags kVerifyFlags, 456 bool kIsVolatile> 457inline void Object::SetField16(MemberOffset field_offset, int16_t new_value) { 458 if (kCheckTransaction) { 459 DCHECK_EQ(false, Runtime::Current()->IsActiveTransaction()); 460 } 461 if (kVerifyFlags & kVerifyThis) { 462 VerifyObject(this); 463 } 464 byte* raw_addr = reinterpret_cast<byte*>(this) + field_offset.Int32Value(); 465 int16_t* word_addr = reinterpret_cast<int16_t*>(raw_addr); 466 if (kIsVolatile) { 467 reinterpret_cast<Atomic<int16_t>*>(word_addr)->StoreSequentiallyConsistent(new_value); 468 } else { 469 reinterpret_cast<Atomic<int16_t>*>(word_addr)->StoreJavaData(new_value); 470 } 471} 472 473template<VerifyObjectFlags kVerifyFlags, bool kIsVolatile> 474inline int32_t Object::GetField32(MemberOffset field_offset) { 475 if (kVerifyFlags & kVerifyThis) { 476 VerifyObject(this); 477 } 478 const byte* raw_addr = reinterpret_cast<const byte*>(this) + field_offset.Int32Value(); 479 const int32_t* word_addr = reinterpret_cast<const int32_t*>(raw_addr); 480 if (UNLIKELY(kIsVolatile)) { 481 return reinterpret_cast<const Atomic<int32_t>*>(word_addr)->LoadSequentiallyConsistent(); 482 } else { 483 return reinterpret_cast<const Atomic<int32_t>*>(word_addr)->LoadJavaData(); 484 } 485} 486 487template<VerifyObjectFlags kVerifyFlags> 488inline int32_t Object::GetField32Volatile(MemberOffset field_offset) { 489 return GetField32<kVerifyFlags, true>(field_offset); 490} 491 492template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags, 493 bool kIsVolatile> 494inline void Object::SetField32(MemberOffset field_offset, int32_t new_value) { 495 if (kCheckTransaction) { 496 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction()); 497 } 498 if (kTransactionActive) { 499 Runtime::Current()->RecordWriteField32(this, field_offset, 500 GetField32<kVerifyFlags, kIsVolatile>(field_offset), 501 kIsVolatile); 502 } 503 if (kVerifyFlags & kVerifyThis) { 504 VerifyObject(this); 505 } 506 byte* raw_addr = reinterpret_cast<byte*>(this) + field_offset.Int32Value(); 507 int32_t* word_addr = reinterpret_cast<int32_t*>(raw_addr); 508 if (kIsVolatile) { 509 reinterpret_cast<Atomic<int32_t>*>(word_addr)->StoreSequentiallyConsistent(new_value); 510 } else { 511 reinterpret_cast<Atomic<int32_t>*>(word_addr)->StoreJavaData(new_value); 512 } 513} 514 515template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> 516inline void Object::SetField32Volatile(MemberOffset field_offset, int32_t new_value) { 517 SetField32<kTransactionActive, kCheckTransaction, kVerifyFlags, true>(field_offset, new_value); 518} 519 520// TODO: Pass memory_order_ and strong/weak as arguments to avoid code duplication? 521 522template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> 523inline bool Object::CasFieldWeakSequentiallyConsistent32(MemberOffset field_offset, 524 int32_t old_value, int32_t new_value) { 525 if (kCheckTransaction) { 526 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction()); 527 } 528 if (kTransactionActive) { 529 Runtime::Current()->RecordWriteField32(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 AtomicInteger* atomic_addr = reinterpret_cast<AtomicInteger*>(raw_addr); 536 537 return atomic_addr->CompareExchangeWeakSequentiallyConsistent(old_value, new_value); 538} 539 540template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> 541inline bool Object::CasFieldWeakRelaxed32(MemberOffset field_offset, 542 int32_t old_value, int32_t new_value) { 543 if (kCheckTransaction) { 544 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction()); 545 } 546 if (kTransactionActive) { 547 Runtime::Current()->RecordWriteField32(this, field_offset, old_value, true); 548 } 549 if (kVerifyFlags & kVerifyThis) { 550 VerifyObject(this); 551 } 552 byte* raw_addr = reinterpret_cast<byte*>(this) + field_offset.Int32Value(); 553 AtomicInteger* atomic_addr = reinterpret_cast<AtomicInteger*>(raw_addr); 554 555 return atomic_addr->CompareExchangeWeakRelaxed(old_value, new_value); 556} 557 558template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> 559inline bool Object::CasFieldStrongSequentiallyConsistent32(MemberOffset field_offset, 560 int32_t old_value, int32_t new_value) { 561 if (kCheckTransaction) { 562 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction()); 563 } 564 if (kTransactionActive) { 565 Runtime::Current()->RecordWriteField32(this, field_offset, old_value, true); 566 } 567 if (kVerifyFlags & kVerifyThis) { 568 VerifyObject(this); 569 } 570 byte* raw_addr = reinterpret_cast<byte*>(this) + field_offset.Int32Value(); 571 AtomicInteger* atomic_addr = reinterpret_cast<AtomicInteger*>(raw_addr); 572 573 return atomic_addr->CompareExchangeStrongSequentiallyConsistent(old_value, new_value); 574} 575 576template<VerifyObjectFlags kVerifyFlags, bool kIsVolatile> 577inline int64_t Object::GetField64(MemberOffset field_offset) { 578 if (kVerifyFlags & kVerifyThis) { 579 VerifyObject(this); 580 } 581 const byte* raw_addr = reinterpret_cast<const byte*>(this) + field_offset.Int32Value(); 582 const int64_t* addr = reinterpret_cast<const int64_t*>(raw_addr); 583 if (kIsVolatile) { 584 return reinterpret_cast<const Atomic<int64_t>*>(addr)->LoadSequentiallyConsistent(); 585 } else { 586 return reinterpret_cast<const Atomic<int64_t>*>(addr)->LoadJavaData(); 587 } 588} 589 590template<VerifyObjectFlags kVerifyFlags> 591inline int64_t Object::GetField64Volatile(MemberOffset field_offset) { 592 return GetField64<kVerifyFlags, true>(field_offset); 593} 594 595template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags, 596 bool kIsVolatile> 597inline void Object::SetField64(MemberOffset field_offset, int64_t new_value) { 598 if (kCheckTransaction) { 599 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction()); 600 } 601 if (kTransactionActive) { 602 Runtime::Current()->RecordWriteField64(this, field_offset, 603 GetField64<kVerifyFlags, kIsVolatile>(field_offset), 604 kIsVolatile); 605 } 606 if (kVerifyFlags & kVerifyThis) { 607 VerifyObject(this); 608 } 609 byte* raw_addr = reinterpret_cast<byte*>(this) + field_offset.Int32Value(); 610 int64_t* addr = reinterpret_cast<int64_t*>(raw_addr); 611 if (kIsVolatile) { 612 reinterpret_cast<Atomic<int64_t>*>(addr)->StoreSequentiallyConsistent(new_value); 613 } else { 614 reinterpret_cast<Atomic<int64_t>*>(addr)->StoreJavaData(new_value); 615 } 616} 617 618template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> 619inline void Object::SetField64Volatile(MemberOffset field_offset, int64_t new_value) { 620 return SetField64<kTransactionActive, kCheckTransaction, kVerifyFlags, true>(field_offset, 621 new_value); 622} 623 624template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> 625inline bool Object::CasFieldWeakSequentiallyConsistent64(MemberOffset field_offset, 626 int64_t old_value, int64_t new_value) { 627 if (kCheckTransaction) { 628 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction()); 629 } 630 if (kTransactionActive) { 631 Runtime::Current()->RecordWriteField64(this, field_offset, old_value, true); 632 } 633 if (kVerifyFlags & kVerifyThis) { 634 VerifyObject(this); 635 } 636 byte* raw_addr = reinterpret_cast<byte*>(this) + field_offset.Int32Value(); 637 Atomic<int64_t>* atomic_addr = reinterpret_cast<Atomic<int64_t>*>(raw_addr); 638 return atomic_addr->CompareExchangeWeakSequentiallyConsistent(old_value, new_value); 639} 640 641template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> 642inline bool Object::CasFieldStrongSequentiallyConsistent64(MemberOffset field_offset, 643 int64_t old_value, int64_t new_value) { 644 if (kCheckTransaction) { 645 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction()); 646 } 647 if (kTransactionActive) { 648 Runtime::Current()->RecordWriteField64(this, field_offset, old_value, true); 649 } 650 if (kVerifyFlags & kVerifyThis) { 651 VerifyObject(this); 652 } 653 byte* raw_addr = reinterpret_cast<byte*>(this) + field_offset.Int32Value(); 654 Atomic<int64_t>* atomic_addr = reinterpret_cast<Atomic<int64_t>*>(raw_addr); 655 return atomic_addr->CompareExchangeStrongSequentiallyConsistent(old_value, new_value); 656} 657 658template<class T, VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption, 659 bool kIsVolatile> 660inline T* Object::GetFieldObject(MemberOffset field_offset) { 661 if (kVerifyFlags & kVerifyThis) { 662 VerifyObject(this); 663 } 664 byte* raw_addr = reinterpret_cast<byte*>(this) + field_offset.Int32Value(); 665 HeapReference<T>* objref_addr = reinterpret_cast<HeapReference<T>*>(raw_addr); 666 T* result = ReadBarrier::Barrier<T, kReadBarrierOption>(this, field_offset, objref_addr); 667 if (kIsVolatile) { 668 // TODO: Refactor to use a SequentiallyConsistent load instead. 669 QuasiAtomic::ThreadFenceAcquire(); // Ensure visibility of operations preceding store. 670 } 671 if (kVerifyFlags & kVerifyReads) { 672 VerifyObject(result); 673 } 674 return result; 675} 676 677template<class T, VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption> 678inline T* Object::GetFieldObjectVolatile(MemberOffset field_offset) { 679 return GetFieldObject<T, kVerifyFlags, kReadBarrierOption, true>(field_offset); 680} 681 682template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags, 683 bool kIsVolatile> 684inline void Object::SetFieldObjectWithoutWriteBarrier(MemberOffset field_offset, 685 Object* new_value) { 686 if (kCheckTransaction) { 687 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction()); 688 } 689 if (kTransactionActive) { 690 mirror::Object* obj; 691 if (kIsVolatile) { 692 obj = GetFieldObjectVolatile<Object>(field_offset); 693 } else { 694 obj = GetFieldObject<Object>(field_offset); 695 } 696 Runtime::Current()->RecordWriteFieldReference(this, field_offset, obj, true); 697 } 698 if (kVerifyFlags & kVerifyThis) { 699 VerifyObject(this); 700 } 701 if (kVerifyFlags & kVerifyWrites) { 702 VerifyObject(new_value); 703 } 704 byte* raw_addr = reinterpret_cast<byte*>(this) + field_offset.Int32Value(); 705 HeapReference<Object>* objref_addr = reinterpret_cast<HeapReference<Object>*>(raw_addr); 706 if (kIsVolatile) { 707 // TODO: Refactor to use a SequentiallyConsistent store instead. 708 QuasiAtomic::ThreadFenceRelease(); // Ensure that prior accesses are visible before store. 709 objref_addr->Assign(new_value); 710 QuasiAtomic::ThreadFenceSequentiallyConsistent(); 711 // Ensure this store occurs before any volatile loads. 712 } else { 713 objref_addr->Assign(new_value); 714 } 715} 716 717template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags, 718 bool kIsVolatile> 719inline void Object::SetFieldObject(MemberOffset field_offset, Object* new_value) { 720 SetFieldObjectWithoutWriteBarrier<kTransactionActive, kCheckTransaction, kVerifyFlags, 721 kIsVolatile>(field_offset, new_value); 722 if (new_value != nullptr) { 723 Runtime::Current()->GetHeap()->WriteBarrierField(this, field_offset, new_value); 724 // TODO: Check field assignment could theoretically cause thread suspension, TODO: fix this. 725 CheckFieldAssignment(field_offset, new_value); 726 } 727} 728 729template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> 730inline void Object::SetFieldObjectVolatile(MemberOffset field_offset, Object* new_value) { 731 SetFieldObject<kTransactionActive, kCheckTransaction, kVerifyFlags, true>(field_offset, 732 new_value); 733} 734 735template <VerifyObjectFlags kVerifyFlags> 736inline HeapReference<Object>* Object::GetFieldObjectReferenceAddr(MemberOffset field_offset) { 737 if (kVerifyFlags & kVerifyThis) { 738 VerifyObject(this); 739 } 740 return reinterpret_cast<HeapReference<Object>*>(reinterpret_cast<byte*>(this) + 741 field_offset.Int32Value()); 742} 743 744template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> 745inline bool Object::CasFieldWeakSequentiallyConsistentObject(MemberOffset field_offset, 746 Object* old_value, Object* new_value) { 747 if (kCheckTransaction) { 748 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction()); 749 } 750 if (kVerifyFlags & kVerifyThis) { 751 VerifyObject(this); 752 } 753 if (kVerifyFlags & kVerifyWrites) { 754 VerifyObject(new_value); 755 } 756 if (kVerifyFlags & kVerifyReads) { 757 VerifyObject(old_value); 758 } 759 if (kTransactionActive) { 760 Runtime::Current()->RecordWriteFieldReference(this, field_offset, old_value, true); 761 } 762 HeapReference<Object> old_ref(HeapReference<Object>::FromMirrorPtr(old_value)); 763 HeapReference<Object> new_ref(HeapReference<Object>::FromMirrorPtr(new_value)); 764 byte* raw_addr = reinterpret_cast<byte*>(this) + field_offset.Int32Value(); 765 Atomic<uint32_t>* atomic_addr = reinterpret_cast<Atomic<uint32_t>*>(raw_addr); 766 767 bool success = atomic_addr->CompareExchangeWeakSequentiallyConsistent(old_ref.reference_, 768 new_ref.reference_); 769 770 if (success) { 771 Runtime::Current()->GetHeap()->WriteBarrierField(this, field_offset, new_value); 772 } 773 return success; 774} 775 776template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> 777inline bool Object::CasFieldStrongSequentiallyConsistentObject(MemberOffset field_offset, 778 Object* old_value, Object* new_value) { 779 if (kCheckTransaction) { 780 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction()); 781 } 782 if (kVerifyFlags & kVerifyThis) { 783 VerifyObject(this); 784 } 785 if (kVerifyFlags & kVerifyWrites) { 786 VerifyObject(new_value); 787 } 788 if (kVerifyFlags & kVerifyReads) { 789 VerifyObject(old_value); 790 } 791 if (kTransactionActive) { 792 Runtime::Current()->RecordWriteFieldReference(this, field_offset, old_value, true); 793 } 794 HeapReference<Object> old_ref(HeapReference<Object>::FromMirrorPtr(old_value)); 795 HeapReference<Object> new_ref(HeapReference<Object>::FromMirrorPtr(new_value)); 796 byte* raw_addr = reinterpret_cast<byte*>(this) + field_offset.Int32Value(); 797 Atomic<uint32_t>* atomic_addr = reinterpret_cast<Atomic<uint32_t>*>(raw_addr); 798 799 bool success = atomic_addr->CompareExchangeStrongSequentiallyConsistent(old_ref.reference_, 800 new_ref.reference_); 801 802 if (success) { 803 Runtime::Current()->GetHeap()->WriteBarrierField(this, field_offset, new_value); 804 } 805 return success; 806} 807 808template<bool kVisitClass, bool kIsStatic, typename Visitor> 809inline void Object::VisitFieldsReferences(uint32_t ref_offsets, const Visitor& visitor) { 810 if (LIKELY(ref_offsets != CLASS_WALK_SUPER)) { 811 if (!kVisitClass) { 812 // Mask out the class from the reference offsets. 813 ref_offsets ^= kWordHighBitMask; 814 } 815 DCHECK_EQ(ClassOffset().Uint32Value(), 0U); 816 // Found a reference offset bitmap. Visit the specified offsets. 817 while (ref_offsets != 0) { 818 size_t right_shift = CLZ(ref_offsets); 819 MemberOffset field_offset = CLASS_OFFSET_FROM_CLZ(right_shift); 820 visitor(this, field_offset, kIsStatic); 821 ref_offsets &= ~(CLASS_HIGH_BIT >> right_shift); 822 } 823 } else { 824 // There is no reference offset bitmap. In the non-static case, walk up the class 825 // inheritance hierarchy and find reference offsets the hard way. In the static case, just 826 // consider this class. 827 for (mirror::Class* klass = kIsStatic ? AsClass() : GetClass(); klass != nullptr; 828 klass = kIsStatic ? nullptr : klass->GetSuperClass()) { 829 size_t num_reference_fields = 830 kIsStatic ? klass->NumReferenceStaticFields() : klass->NumReferenceInstanceFields(); 831 if (num_reference_fields == 0u) { 832 continue; 833 } 834 MemberOffset field_offset = kIsStatic 835 ? klass->GetFirstReferenceStaticFieldOffset() 836 : klass->GetFirstReferenceInstanceFieldOffset(); 837 for (size_t i = 0; i < num_reference_fields; ++i) { 838 // TODO: Do a simpler check? 839 if (kVisitClass || field_offset.Uint32Value() != ClassOffset().Uint32Value()) { 840 visitor(this, field_offset, kIsStatic); 841 } 842 field_offset = MemberOffset(field_offset.Uint32Value() + 843 sizeof(mirror::HeapReference<mirror::Object>)); 844 } 845 } 846 } 847} 848 849template<bool kVisitClass, typename Visitor> 850inline void Object::VisitInstanceFieldsReferences(mirror::Class* klass, const Visitor& visitor) { 851 VisitFieldsReferences<kVisitClass, false>( 852 klass->GetReferenceInstanceOffsets<kVerifyNone>(), visitor); 853} 854 855template<bool kVisitClass, typename Visitor> 856inline void Object::VisitStaticFieldsReferences(mirror::Class* klass, const Visitor& visitor) { 857 DCHECK(!klass->IsTemp()); 858 klass->VisitFieldsReferences<kVisitClass, true>( 859 klass->GetReferenceStaticOffsets<kVerifyNone>(), visitor); 860} 861 862template <const bool kVisitClass, VerifyObjectFlags kVerifyFlags, typename Visitor, 863 typename JavaLangRefVisitor> 864inline void Object::VisitReferences(const Visitor& visitor, 865 const JavaLangRefVisitor& ref_visitor) { 866 mirror::Class* klass = GetClass<kVerifyFlags>(); 867 if (klass == Class::GetJavaLangClass()) { 868 AsClass<kVerifyNone>()->VisitReferences<kVisitClass>(klass, visitor); 869 } else if (klass->IsArrayClass()) { 870 if (klass->IsObjectArrayClass<kVerifyNone>()) { 871 AsObjectArray<mirror::Object, kVerifyNone>()->VisitReferences<kVisitClass>(visitor); 872 } else if (kVisitClass) { 873 visitor(this, ClassOffset(), false); 874 } 875 } else { 876 DCHECK(!klass->IsVariableSize()); 877 VisitInstanceFieldsReferences<kVisitClass>(klass, visitor); 878 if (UNLIKELY(klass->IsTypeOfReferenceClass<kVerifyNone>())) { 879 ref_visitor(klass, AsReference()); 880 } 881 } 882} 883} // namespace mirror 884} // namespace art 885 886#endif // ART_RUNTIME_MIRROR_OBJECT_INL_H_ 887