object-inl.h revision 928033d81f63912f669acd27a72897694eb31db6
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 "array-inl.h" 23#include "art_field.h" 24#include "art_method.h" 25#include "atomic.h" 26#include "class-inl.h" 27#include "class_flags.h" 28#include "class_linker.h" 29#include "dex_cache.h" 30#include "heap_poisoning.h" 31#include "lock_word-inl.h" 32#include "monitor.h" 33#include "obj_ptr-inl.h" 34#include "object-readbarrier-inl.h" 35#include "object_array-inl.h" 36#include "object_reference-inl.h" 37#include "read_barrier-inl.h" 38#include "reference.h" 39#include "runtime.h" 40#include "string-inl.h" 41#include "throwable.h" 42 43namespace art { 44namespace mirror { 45 46inline uint32_t Object::ClassSize(PointerSize pointer_size) { 47 uint32_t vtable_entries = kVTableLength; 48 return Class::ComputeClassSize(true, vtable_entries, 0, 0, 0, 0, 0, pointer_size); 49} 50 51template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption> 52inline Class* Object::GetClass() { 53 return GetFieldObject<Class, kVerifyFlags, kReadBarrierOption>( 54 OFFSET_OF_OBJECT_MEMBER(Object, klass_)); 55} 56 57template<VerifyObjectFlags kVerifyFlags> 58inline void Object::SetClass(ObjPtr<Class> new_klass) { 59 // new_klass may be null prior to class linker initialization. 60 // We don't mark the card as this occurs as part of object allocation. Not all objects have 61 // backing cards, such as large objects. 62 // We use non transactional version since we can't undo this write. We also disable checking as 63 // we may run in transaction mode here. 64 SetFieldObjectWithoutWriteBarrier<false, false, 65 static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis)>( 66 OFFSET_OF_OBJECT_MEMBER(Object, klass_), new_klass); 67} 68 69template<VerifyObjectFlags kVerifyFlags> 70inline void Object::SetLockWord(LockWord new_val, bool as_volatile) { 71 // Force use of non-transactional mode and do not check. 72 if (as_volatile) { 73 SetField32Volatile<false, false, kVerifyFlags>( 74 OFFSET_OF_OBJECT_MEMBER(Object, monitor_), new_val.GetValue()); 75 } else { 76 SetField32<false, false, kVerifyFlags>( 77 OFFSET_OF_OBJECT_MEMBER(Object, monitor_), new_val.GetValue()); 78 } 79} 80 81inline bool Object::CasLockWordWeakSequentiallyConsistent(LockWord old_val, LockWord new_val) { 82 // Force use of non-transactional mode and do not check. 83 return CasFieldWeakSequentiallyConsistent32<false, false>( 84 OFFSET_OF_OBJECT_MEMBER(Object, monitor_), old_val.GetValue(), new_val.GetValue()); 85} 86 87inline bool Object::CasLockWordWeakAcquire(LockWord old_val, LockWord new_val) { 88 // Force use of non-transactional mode and do not check. 89 return CasFieldWeakAcquire32<false, false>( 90 OFFSET_OF_OBJECT_MEMBER(Object, monitor_), old_val.GetValue(), new_val.GetValue()); 91} 92 93inline uint32_t Object::GetLockOwnerThreadId() { 94 return Monitor::GetLockOwnerThreadId(this); 95} 96 97inline mirror::Object* Object::MonitorEnter(Thread* self) { 98 return Monitor::MonitorEnter(self, this, /*trylock*/false); 99} 100 101inline mirror::Object* Object::MonitorTryEnter(Thread* self) { 102 return Monitor::MonitorEnter(self, this, /*trylock*/true); 103} 104 105inline bool Object::MonitorExit(Thread* self) { 106 return Monitor::MonitorExit(self, this); 107} 108 109inline void Object::Notify(Thread* self) { 110 Monitor::Notify(self, this); 111} 112 113inline void Object::NotifyAll(Thread* self) { 114 Monitor::NotifyAll(self, this); 115} 116 117inline void Object::Wait(Thread* self) { 118 Monitor::Wait(self, this, 0, 0, true, kWaiting); 119} 120 121inline void Object::Wait(Thread* self, int64_t ms, int32_t ns) { 122 Monitor::Wait(self, this, ms, ns, true, kTimedWaiting); 123} 124 125inline uint32_t Object::GetMarkBit() { 126#ifdef USE_READ_BARRIER 127 return GetLockWord(false).MarkBitState(); 128#else 129 LOG(FATAL) << "Unreachable"; 130 UNREACHABLE(); 131#endif 132} 133 134inline void Object::SetReadBarrierState(uint32_t rb_state) { 135 if (!kUseBakerReadBarrier) { 136 LOG(FATAL) << "Unreachable"; 137 UNREACHABLE(); 138 } 139 DCHECK(ReadBarrier::IsValidReadBarrierState(rb_state)) << rb_state; 140 LockWord lw = GetLockWord(false); 141 lw.SetReadBarrierState(rb_state); 142 SetLockWord(lw, false); 143} 144 145inline void Object::AssertReadBarrierState() const { 146 CHECK(kUseBakerReadBarrier); 147 Object* obj = const_cast<Object*>(this); 148 DCHECK(obj->GetReadBarrierState() == ReadBarrier::WhiteState()) 149 << "Bad Baker pointer: obj=" << reinterpret_cast<void*>(obj) 150 << " rb_state" << reinterpret_cast<void*>(obj->GetReadBarrierState()); 151} 152 153template<VerifyObjectFlags kVerifyFlags> 154inline bool Object::VerifierInstanceOf(ObjPtr<Class> klass) { 155 DCHECK(klass != nullptr); 156 DCHECK(GetClass<kVerifyFlags>() != nullptr); 157 return klass->IsInterface() || InstanceOf(klass); 158} 159 160template<VerifyObjectFlags kVerifyFlags> 161inline bool Object::InstanceOf(ObjPtr<Class> klass) { 162 DCHECK(klass != nullptr); 163 DCHECK(GetClass<kVerifyNone>() != nullptr); 164 return klass->IsAssignableFrom(GetClass<kVerifyFlags>()); 165} 166 167template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption> 168inline bool Object::IsClass() { 169 Class* java_lang_Class = GetClass<kVerifyFlags, kReadBarrierOption>()-> 170 template GetClass<kVerifyFlags, kReadBarrierOption>(); 171 return GetClass<static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis), 172 kReadBarrierOption>() == java_lang_Class; 173} 174 175template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption> 176inline Class* Object::AsClass() { 177 DCHECK((IsClass<kVerifyFlags, kReadBarrierOption>())); 178 return down_cast<Class*>(this); 179} 180 181template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption> 182inline bool Object::IsObjectArray() { 183 constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis); 184 return IsArrayInstance<kVerifyFlags, kReadBarrierOption>() && 185 !GetClass<kNewFlags, kReadBarrierOption>()-> 186 template GetComponentType<kNewFlags, kReadBarrierOption>()->IsPrimitive(); 187} 188 189template<class T, VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption> 190inline ObjectArray<T>* Object::AsObjectArray() { 191 DCHECK((IsObjectArray<kVerifyFlags, kReadBarrierOption>())); 192 return down_cast<ObjectArray<T>*>(this); 193} 194 195template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption> 196inline bool Object::IsArrayInstance() { 197 return GetClass<kVerifyFlags, kReadBarrierOption>()-> 198 template IsArrayClass<kVerifyFlags, kReadBarrierOption>(); 199} 200 201template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption> 202inline bool Object::IsReferenceInstance() { 203 return GetClass<kVerifyFlags, kReadBarrierOption>()->IsTypeOfReferenceClass(); 204} 205 206template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption> 207inline Reference* Object::AsReference() { 208 DCHECK((IsReferenceInstance<kVerifyFlags, kReadBarrierOption>())); 209 return down_cast<Reference*>(this); 210} 211 212template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption> 213inline Array* Object::AsArray() { 214 DCHECK((IsArrayInstance<kVerifyFlags, kReadBarrierOption>())); 215 return down_cast<Array*>(this); 216} 217 218template<VerifyObjectFlags kVerifyFlags> 219inline BooleanArray* Object::AsBooleanArray() { 220 constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis); 221 DCHECK(GetClass<kVerifyFlags>()->IsArrayClass()); 222 DCHECK(GetClass<kNewFlags>()->GetComponentType()->IsPrimitiveBoolean()); 223 return down_cast<BooleanArray*>(this); 224} 225 226template<VerifyObjectFlags kVerifyFlags> 227inline ByteArray* Object::AsByteArray() { 228 constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis); 229 DCHECK(GetClass<kVerifyFlags>()->IsArrayClass()); 230 DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveByte()); 231 return down_cast<ByteArray*>(this); 232} 233 234template<VerifyObjectFlags kVerifyFlags> 235inline ByteArray* Object::AsByteSizedArray() { 236 constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis); 237 DCHECK(GetClass<kVerifyFlags>()->IsArrayClass()); 238 DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveByte() || 239 GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveBoolean()); 240 return down_cast<ByteArray*>(this); 241} 242 243template<VerifyObjectFlags kVerifyFlags> 244inline CharArray* Object::AsCharArray() { 245 constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis); 246 DCHECK(GetClass<kVerifyFlags>()->IsArrayClass()); 247 DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveChar()); 248 return down_cast<CharArray*>(this); 249} 250 251template<VerifyObjectFlags kVerifyFlags> 252inline ShortArray* Object::AsShortArray() { 253 constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis); 254 DCHECK(GetClass<kVerifyFlags>()->IsArrayClass()); 255 DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveShort()); 256 return down_cast<ShortArray*>(this); 257} 258 259template<VerifyObjectFlags kVerifyFlags> 260inline ShortArray* Object::AsShortSizedArray() { 261 constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis); 262 DCHECK(GetClass<kVerifyFlags>()->IsArrayClass()); 263 DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveShort() || 264 GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveChar()); 265 return down_cast<ShortArray*>(this); 266} 267 268template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption> 269inline bool Object::IsIntArray() { 270 constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis); 271 ObjPtr<Class> klass = GetClass<kVerifyFlags, kReadBarrierOption>(); 272 ObjPtr<Class> component_type = klass->GetComponentType<kVerifyFlags, kReadBarrierOption>(); 273 return component_type != nullptr && component_type->template IsPrimitiveInt<kNewFlags>(); 274} 275 276template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption> 277inline IntArray* Object::AsIntArray() { 278 DCHECK((IsIntArray<kVerifyFlags, kReadBarrierOption>())); 279 return down_cast<IntArray*>(this); 280} 281 282template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption> 283inline bool Object::IsLongArray() { 284 constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis); 285 ObjPtr<Class> klass = GetClass<kVerifyFlags, kReadBarrierOption>(); 286 ObjPtr<Class> component_type = klass->GetComponentType<kVerifyFlags, kReadBarrierOption>(); 287 return component_type != nullptr && component_type->template IsPrimitiveLong<kNewFlags>(); 288} 289 290template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption> 291inline LongArray* Object::AsLongArray() { 292 DCHECK((IsLongArray<kVerifyFlags, kReadBarrierOption>())); 293 return down_cast<LongArray*>(this); 294} 295 296template<VerifyObjectFlags kVerifyFlags> 297inline bool Object::IsFloatArray() { 298 constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis); 299 auto* component_type = GetClass<kVerifyFlags>()->GetComponentType(); 300 return component_type != nullptr && component_type->template IsPrimitiveFloat<kNewFlags>(); 301} 302 303template<VerifyObjectFlags kVerifyFlags> 304inline FloatArray* Object::AsFloatArray() { 305 DCHECK(IsFloatArray<kVerifyFlags>()); 306 constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis); 307 DCHECK(GetClass<kVerifyFlags>()->IsArrayClass()); 308 DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveFloat()); 309 return down_cast<FloatArray*>(this); 310} 311 312template<VerifyObjectFlags kVerifyFlags> 313inline bool Object::IsDoubleArray() { 314 constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis); 315 auto* component_type = GetClass<kVerifyFlags>()->GetComponentType(); 316 return component_type != nullptr && component_type->template IsPrimitiveDouble<kNewFlags>(); 317} 318 319template<VerifyObjectFlags kVerifyFlags> 320inline DoubleArray* Object::AsDoubleArray() { 321 DCHECK(IsDoubleArray<kVerifyFlags>()); 322 constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis); 323 DCHECK(GetClass<kVerifyFlags>()->IsArrayClass()); 324 DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveDouble()); 325 return down_cast<DoubleArray*>(this); 326} 327 328template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption> 329inline bool Object::IsString() { 330 return GetClass<kVerifyFlags, kReadBarrierOption>()->IsStringClass(); 331} 332 333template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption> 334inline String* Object::AsString() { 335 DCHECK((IsString<kVerifyFlags, kReadBarrierOption>())); 336 return down_cast<String*>(this); 337} 338 339template<VerifyObjectFlags kVerifyFlags> 340inline Throwable* Object::AsThrowable() { 341 DCHECK(GetClass<kVerifyFlags>()->IsThrowableClass()); 342 return down_cast<Throwable*>(this); 343} 344 345template<VerifyObjectFlags kVerifyFlags> 346inline bool Object::IsWeakReferenceInstance() { 347 return GetClass<kVerifyFlags>()->IsWeakReferenceClass(); 348} 349 350template<VerifyObjectFlags kVerifyFlags> 351inline bool Object::IsSoftReferenceInstance() { 352 return GetClass<kVerifyFlags>()->IsSoftReferenceClass(); 353} 354 355template<VerifyObjectFlags kVerifyFlags> 356inline bool Object::IsFinalizerReferenceInstance() { 357 return GetClass<kVerifyFlags>()->IsFinalizerReferenceClass(); 358} 359 360template<VerifyObjectFlags kVerifyFlags> 361inline FinalizerReference* Object::AsFinalizerReference() { 362 DCHECK(IsFinalizerReferenceInstance<kVerifyFlags>()); 363 return down_cast<FinalizerReference*>(this); 364} 365 366template<VerifyObjectFlags kVerifyFlags> 367inline bool Object::IsPhantomReferenceInstance() { 368 return GetClass<kVerifyFlags>()->IsPhantomReferenceClass(); 369} 370 371template<VerifyObjectFlags kVerifyFlags> 372inline size_t Object::SizeOf() { 373 // Read barrier is never required for SizeOf since objects sizes are constant. Reading from-space 374 // values is OK because of that. 375 static constexpr ReadBarrierOption kReadBarrierOption = kWithoutReadBarrier; 376 size_t result; 377 constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis); 378 if (IsArrayInstance<kVerifyFlags, kReadBarrierOption>()) { 379 result = AsArray<kNewFlags, kReadBarrierOption>()-> 380 template SizeOf<kNewFlags, kReadBarrierOption>(); 381 } else if (IsClass<kNewFlags, kReadBarrierOption>()) { 382 result = AsClass<kNewFlags, kReadBarrierOption>()-> 383 template SizeOf<kNewFlags, kReadBarrierOption>(); 384 } else if (GetClass<kNewFlags, kReadBarrierOption>()->IsStringClass()) { 385 result = AsString<kNewFlags, kReadBarrierOption>()-> 386 template SizeOf<kNewFlags>(); 387 } else { 388 result = GetClass<kNewFlags, kReadBarrierOption>()-> 389 template GetObjectSize<kNewFlags, kReadBarrierOption>(); 390 } 391 DCHECK_GE(result, sizeof(Object)) 392 << " class=" << Class::PrettyClass(GetClass<kNewFlags, kReadBarrierOption>()); 393 return result; 394} 395 396template<VerifyObjectFlags kVerifyFlags, bool kIsVolatile> 397inline int8_t Object::GetFieldByte(MemberOffset field_offset) { 398 if (kVerifyFlags & kVerifyThis) { 399 VerifyObject(this); 400 } 401 return GetField<int8_t, kIsVolatile>(field_offset); 402} 403 404template<VerifyObjectFlags kVerifyFlags> 405inline uint8_t Object::GetFieldBooleanVolatile(MemberOffset field_offset) { 406 return GetFieldBoolean<kVerifyFlags, true>(field_offset); 407} 408 409template<VerifyObjectFlags kVerifyFlags> 410inline int8_t Object::GetFieldByteVolatile(MemberOffset field_offset) { 411 return GetFieldByte<kVerifyFlags, true>(field_offset); 412} 413 414template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags, 415 bool kIsVolatile> 416inline void Object::SetFieldBoolean(MemberOffset field_offset, uint8_t new_value) 417 REQUIRES_SHARED(Locks::mutator_lock_) { 418 if (kCheckTransaction) { 419 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction()); 420 } 421 if (kTransactionActive) { 422 Runtime::Current()->RecordWriteFieldBoolean(this, field_offset, 423 GetFieldBoolean<kVerifyFlags, kIsVolatile>(field_offset), 424 kIsVolatile); 425 } 426 if (kVerifyFlags & kVerifyThis) { 427 VerifyObject(this); 428 } 429 SetField<uint8_t, kIsVolatile>(field_offset, new_value); 430} 431 432template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags, 433 bool kIsVolatile> 434inline void Object::SetFieldByte(MemberOffset field_offset, int8_t new_value) 435 REQUIRES_SHARED(Locks::mutator_lock_) { 436 if (kCheckTransaction) { 437 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction()); 438 } 439 if (kTransactionActive) { 440 Runtime::Current()->RecordWriteFieldByte(this, field_offset, 441 GetFieldByte<kVerifyFlags, kIsVolatile>(field_offset), 442 kIsVolatile); 443 } 444 if (kVerifyFlags & kVerifyThis) { 445 VerifyObject(this); 446 } 447 SetField<int8_t, kIsVolatile>(field_offset, new_value); 448} 449 450template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> 451inline void Object::SetFieldBooleanVolatile(MemberOffset field_offset, uint8_t new_value) { 452 return SetFieldBoolean<kTransactionActive, kCheckTransaction, kVerifyFlags, true>( 453 field_offset, new_value); 454} 455 456template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> 457inline void Object::SetFieldByteVolatile(MemberOffset field_offset, int8_t new_value) { 458 return SetFieldByte<kTransactionActive, kCheckTransaction, kVerifyFlags, true>( 459 field_offset, new_value); 460} 461 462template<VerifyObjectFlags kVerifyFlags, bool kIsVolatile> 463inline uint16_t Object::GetFieldChar(MemberOffset field_offset) { 464 if (kVerifyFlags & kVerifyThis) { 465 VerifyObject(this); 466 } 467 return GetField<uint16_t, kIsVolatile>(field_offset); 468} 469 470template<VerifyObjectFlags kVerifyFlags, bool kIsVolatile> 471inline int16_t Object::GetFieldShort(MemberOffset field_offset) { 472 if (kVerifyFlags & kVerifyThis) { 473 VerifyObject(this); 474 } 475 return GetField<int16_t, kIsVolatile>(field_offset); 476} 477 478template<VerifyObjectFlags kVerifyFlags> 479inline uint16_t Object::GetFieldCharVolatile(MemberOffset field_offset) { 480 return GetFieldChar<kVerifyFlags, true>(field_offset); 481} 482 483template<VerifyObjectFlags kVerifyFlags> 484inline int16_t Object::GetFieldShortVolatile(MemberOffset field_offset) { 485 return GetFieldShort<kVerifyFlags, true>(field_offset); 486} 487 488template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags, 489 bool kIsVolatile> 490inline void Object::SetFieldChar(MemberOffset field_offset, uint16_t new_value) { 491 if (kCheckTransaction) { 492 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction()); 493 } 494 if (kTransactionActive) { 495 Runtime::Current()->RecordWriteFieldChar(this, field_offset, 496 GetFieldChar<kVerifyFlags, kIsVolatile>(field_offset), 497 kIsVolatile); 498 } 499 if (kVerifyFlags & kVerifyThis) { 500 VerifyObject(this); 501 } 502 SetField<uint16_t, kIsVolatile>(field_offset, new_value); 503} 504 505template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags, 506 bool kIsVolatile> 507inline void Object::SetFieldShort(MemberOffset field_offset, int16_t new_value) { 508 if (kCheckTransaction) { 509 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction()); 510 } 511 if (kTransactionActive) { 512 Runtime::Current()->RecordWriteFieldChar(this, field_offset, 513 GetFieldShort<kVerifyFlags, kIsVolatile>(field_offset), 514 kIsVolatile); 515 } 516 if (kVerifyFlags & kVerifyThis) { 517 VerifyObject(this); 518 } 519 SetField<int16_t, kIsVolatile>(field_offset, new_value); 520} 521 522template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> 523inline void Object::SetFieldCharVolatile(MemberOffset field_offset, uint16_t new_value) { 524 return SetFieldChar<kTransactionActive, kCheckTransaction, kVerifyFlags, true>( 525 field_offset, new_value); 526} 527 528template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> 529inline void Object::SetFieldShortVolatile(MemberOffset field_offset, int16_t new_value) { 530 return SetFieldShort<kTransactionActive, kCheckTransaction, kVerifyFlags, true>( 531 field_offset, new_value); 532} 533 534template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags, 535 bool kIsVolatile> 536inline void Object::SetField32(MemberOffset field_offset, int32_t new_value) { 537 if (kCheckTransaction) { 538 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction()); 539 } 540 if (kTransactionActive) { 541 Runtime::Current()->RecordWriteField32(this, field_offset, 542 GetField32<kVerifyFlags, kIsVolatile>(field_offset), 543 kIsVolatile); 544 } 545 if (kVerifyFlags & kVerifyThis) { 546 VerifyObject(this); 547 } 548 SetField<int32_t, kIsVolatile>(field_offset, new_value); 549} 550 551template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> 552inline void Object::SetField32Volatile(MemberOffset field_offset, int32_t new_value) { 553 SetField32<kTransactionActive, kCheckTransaction, kVerifyFlags, true>(field_offset, new_value); 554} 555 556template<bool kCheckTransaction, VerifyObjectFlags kVerifyFlags, bool kIsVolatile> 557inline void Object::SetField32Transaction(MemberOffset field_offset, int32_t new_value) { 558 if (Runtime::Current()->IsActiveTransaction()) { 559 SetField32<true, kCheckTransaction, kVerifyFlags, kIsVolatile>(field_offset, new_value); 560 } else { 561 SetField32<false, kCheckTransaction, kVerifyFlags, kIsVolatile>(field_offset, new_value); 562 } 563} 564 565// TODO: Pass memory_order_ and strong/weak as arguments to avoid code duplication? 566 567template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> 568inline bool Object::CasFieldWeakSequentiallyConsistent32(MemberOffset field_offset, 569 int32_t old_value, int32_t new_value) { 570 if (kCheckTransaction) { 571 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction()); 572 } 573 if (kTransactionActive) { 574 Runtime::Current()->RecordWriteField32(this, field_offset, old_value, true); 575 } 576 if (kVerifyFlags & kVerifyThis) { 577 VerifyObject(this); 578 } 579 uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value(); 580 AtomicInteger* atomic_addr = reinterpret_cast<AtomicInteger*>(raw_addr); 581 582 return atomic_addr->CompareAndSetWeakSequentiallyConsistent(old_value, new_value); 583} 584 585template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> 586inline bool Object::CasFieldWeakAcquire32(MemberOffset field_offset, 587 int32_t old_value, int32_t new_value) { 588 if (kCheckTransaction) { 589 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction()); 590 } 591 if (kTransactionActive) { 592 Runtime::Current()->RecordWriteField32(this, field_offset, old_value, true); 593 } 594 if (kVerifyFlags & kVerifyThis) { 595 VerifyObject(this); 596 } 597 uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value(); 598 AtomicInteger* atomic_addr = reinterpret_cast<AtomicInteger*>(raw_addr); 599 600 return atomic_addr->CompareAndSetWeakAcquire(old_value, new_value); 601} 602 603template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> 604inline bool Object::CasFieldWeakRelease32(MemberOffset field_offset, 605 int32_t old_value, int32_t new_value) { 606 if (kCheckTransaction) { 607 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction()); 608 } 609 if (kTransactionActive) { 610 Runtime::Current()->RecordWriteField32(this, field_offset, old_value, true); 611 } 612 if (kVerifyFlags & kVerifyThis) { 613 VerifyObject(this); 614 } 615 uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value(); 616 AtomicInteger* atomic_addr = reinterpret_cast<AtomicInteger*>(raw_addr); 617 618 return atomic_addr->CompareAndSetWeakRelease(old_value, new_value); 619} 620 621template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> 622inline bool Object::CasFieldStrongSequentiallyConsistent32(MemberOffset field_offset, 623 int32_t old_value, int32_t new_value) { 624 if (kCheckTransaction) { 625 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction()); 626 } 627 if (kTransactionActive) { 628 Runtime::Current()->RecordWriteField32(this, field_offset, old_value, true); 629 } 630 if (kVerifyFlags & kVerifyThis) { 631 VerifyObject(this); 632 } 633 uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value(); 634 AtomicInteger* atomic_addr = reinterpret_cast<AtomicInteger*>(raw_addr); 635 636 return atomic_addr->CompareAndSetStrongSequentiallyConsistent(old_value, new_value); 637} 638 639template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags, 640 bool kIsVolatile> 641inline void Object::SetField64(MemberOffset field_offset, int64_t new_value) { 642 if (kCheckTransaction) { 643 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction()); 644 } 645 if (kTransactionActive) { 646 Runtime::Current()->RecordWriteField64(this, field_offset, 647 GetField64<kVerifyFlags, kIsVolatile>(field_offset), 648 kIsVolatile); 649 } 650 if (kVerifyFlags & kVerifyThis) { 651 VerifyObject(this); 652 } 653 SetField<int64_t, kIsVolatile>(field_offset, new_value); 654} 655 656template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> 657inline void Object::SetField64Volatile(MemberOffset field_offset, int64_t new_value) { 658 return SetField64<kTransactionActive, kCheckTransaction, kVerifyFlags, true>(field_offset, 659 new_value); 660} 661 662template<bool kCheckTransaction, VerifyObjectFlags kVerifyFlags, bool kIsVolatile> 663inline void Object::SetField64Transaction(MemberOffset field_offset, int32_t new_value) { 664 if (Runtime::Current()->IsActiveTransaction()) { 665 SetField64<true, kCheckTransaction, kVerifyFlags, kIsVolatile>(field_offset, new_value); 666 } else { 667 SetField64<false, kCheckTransaction, kVerifyFlags, kIsVolatile>(field_offset, new_value); 668 } 669} 670 671template<typename kSize> 672inline kSize Object::GetFieldAcquire(MemberOffset field_offset) { 673 const uint8_t* raw_addr = reinterpret_cast<const uint8_t*>(this) + field_offset.Int32Value(); 674 const kSize* addr = reinterpret_cast<const kSize*>(raw_addr); 675 return reinterpret_cast<const Atomic<kSize>*>(addr)->LoadAcquire(); 676} 677 678template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> 679inline bool Object::CasFieldWeakSequentiallyConsistent64(MemberOffset field_offset, 680 int64_t old_value, int64_t new_value) { 681 if (kCheckTransaction) { 682 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction()); 683 } 684 if (kTransactionActive) { 685 Runtime::Current()->RecordWriteField64(this, field_offset, old_value, true); 686 } 687 if (kVerifyFlags & kVerifyThis) { 688 VerifyObject(this); 689 } 690 uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value(); 691 Atomic<int64_t>* atomic_addr = reinterpret_cast<Atomic<int64_t>*>(raw_addr); 692 return atomic_addr->CompareAndSetWeakSequentiallyConsistent(old_value, new_value); 693} 694 695template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> 696inline bool Object::CasFieldStrongSequentiallyConsistent64(MemberOffset field_offset, 697 int64_t old_value, int64_t new_value) { 698 if (kCheckTransaction) { 699 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction()); 700 } 701 if (kTransactionActive) { 702 Runtime::Current()->RecordWriteField64(this, field_offset, old_value, true); 703 } 704 if (kVerifyFlags & kVerifyThis) { 705 VerifyObject(this); 706 } 707 uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value(); 708 Atomic<int64_t>* atomic_addr = reinterpret_cast<Atomic<int64_t>*>(raw_addr); 709 return atomic_addr->CompareAndSetStrongSequentiallyConsistent(old_value, new_value); 710} 711 712template<class T, VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption, 713 bool kIsVolatile> 714inline T* Object::GetFieldObject(MemberOffset field_offset) { 715 if (kVerifyFlags & kVerifyThis) { 716 VerifyObject(this); 717 } 718 uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value(); 719 HeapReference<T>* objref_addr = reinterpret_cast<HeapReference<T>*>(raw_addr); 720 T* result = ReadBarrier::Barrier<T, kIsVolatile, kReadBarrierOption>( 721 this, 722 field_offset, 723 objref_addr); 724 if (kVerifyFlags & kVerifyReads) { 725 VerifyObject(result); 726 } 727 return result; 728} 729 730template<class T, VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption> 731inline T* Object::GetFieldObjectVolatile(MemberOffset field_offset) { 732 return GetFieldObject<T, kVerifyFlags, kReadBarrierOption, true>(field_offset); 733} 734 735template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags, 736 bool kIsVolatile> 737inline void Object::SetFieldObjectWithoutWriteBarrier(MemberOffset field_offset, 738 ObjPtr<Object> new_value) { 739 if (kCheckTransaction) { 740 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction()); 741 } 742 if (kTransactionActive) { 743 ObjPtr<Object> obj; 744 if (kIsVolatile) { 745 obj = GetFieldObjectVolatile<Object>(field_offset); 746 } else { 747 obj = GetFieldObject<Object>(field_offset); 748 } 749 Runtime::Current()->RecordWriteFieldReference(this, field_offset, obj.Ptr(), true); 750 } 751 if (kVerifyFlags & kVerifyThis) { 752 VerifyObject(this); 753 } 754 if (kVerifyFlags & kVerifyWrites) { 755 VerifyObject(new_value); 756 } 757 uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value(); 758 HeapReference<Object>* objref_addr = reinterpret_cast<HeapReference<Object>*>(raw_addr); 759 objref_addr->Assign<kIsVolatile>(new_value.Ptr()); 760} 761 762template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags, 763 bool kIsVolatile> 764inline void Object::SetFieldObject(MemberOffset field_offset, ObjPtr<Object> new_value) { 765 SetFieldObjectWithoutWriteBarrier<kTransactionActive, kCheckTransaction, kVerifyFlags, 766 kIsVolatile>(field_offset, new_value); 767 if (new_value != nullptr) { 768 Runtime::Current()->GetHeap()->WriteBarrierField(this, field_offset, new_value); 769 // TODO: Check field assignment could theoretically cause thread suspension, TODO: fix this. 770 CheckFieldAssignment(field_offset, new_value); 771 } 772} 773 774template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> 775inline void Object::SetFieldObjectVolatile(MemberOffset field_offset, ObjPtr<Object> new_value) { 776 SetFieldObject<kTransactionActive, kCheckTransaction, kVerifyFlags, true>(field_offset, 777 new_value); 778} 779 780template<bool kCheckTransaction, VerifyObjectFlags kVerifyFlags, bool kIsVolatile> 781inline void Object::SetFieldObjectTransaction(MemberOffset field_offset, ObjPtr<Object> new_value) { 782 if (Runtime::Current()->IsActiveTransaction()) { 783 SetFieldObject<true, kCheckTransaction, kVerifyFlags, kIsVolatile>(field_offset, new_value); 784 } else { 785 SetFieldObject<false, kCheckTransaction, kVerifyFlags, kIsVolatile>(field_offset, new_value); 786 } 787} 788 789template <VerifyObjectFlags kVerifyFlags> 790inline HeapReference<Object>* Object::GetFieldObjectReferenceAddr(MemberOffset field_offset) { 791 if (kVerifyFlags & kVerifyThis) { 792 VerifyObject(this); 793 } 794 return reinterpret_cast<HeapReference<Object>*>(reinterpret_cast<uint8_t*>(this) + 795 field_offset.Int32Value()); 796} 797 798template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> 799inline bool Object::CasFieldWeakSequentiallyConsistentObject(MemberOffset field_offset, 800 ObjPtr<Object> old_value, 801 ObjPtr<Object> new_value) { 802 bool success = CasFieldWeakSequentiallyConsistentObjectWithoutWriteBarrier< 803 kTransactionActive, kCheckTransaction, kVerifyFlags>(field_offset, old_value, new_value); 804 if (success) { 805 Runtime::Current()->GetHeap()->WriteBarrierField(this, field_offset, new_value); 806 } 807 return success; 808} 809 810template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> 811inline bool Object::CasFieldWeakSequentiallyConsistentObjectWithoutWriteBarrier( 812 MemberOffset field_offset, 813 ObjPtr<Object> old_value, 814 ObjPtr<Object> new_value) { 815 if (kCheckTransaction) { 816 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction()); 817 } 818 if (kVerifyFlags & kVerifyThis) { 819 VerifyObject(this); 820 } 821 if (kVerifyFlags & kVerifyWrites) { 822 VerifyObject(new_value); 823 } 824 if (kVerifyFlags & kVerifyReads) { 825 VerifyObject(old_value); 826 } 827 if (kTransactionActive) { 828 Runtime::Current()->RecordWriteFieldReference(this, field_offset, old_value, true); 829 } 830 uint32_t old_ref(PtrCompression<kPoisonHeapReferences, Object>::Compress(old_value)); 831 uint32_t new_ref(PtrCompression<kPoisonHeapReferences, Object>::Compress(new_value)); 832 uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value(); 833 Atomic<uint32_t>* atomic_addr = reinterpret_cast<Atomic<uint32_t>*>(raw_addr); 834 835 bool success = atomic_addr->CompareAndSetWeakSequentiallyConsistent(old_ref, new_ref); 836 return success; 837} 838 839template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> 840inline bool Object::CasFieldStrongSequentiallyConsistentObject(MemberOffset field_offset, 841 ObjPtr<Object> old_value, 842 ObjPtr<Object> new_value) { 843 bool success = CasFieldStrongSequentiallyConsistentObjectWithoutWriteBarrier< 844 kTransactionActive, kCheckTransaction, kVerifyFlags>(field_offset, old_value, new_value); 845 if (success) { 846 Runtime::Current()->GetHeap()->WriteBarrierField(this, field_offset, new_value); 847 } 848 return success; 849} 850 851template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> 852inline bool Object::CasFieldStrongSequentiallyConsistentObjectWithoutWriteBarrier( 853 MemberOffset field_offset, 854 ObjPtr<Object> old_value, 855 ObjPtr<Object> new_value) { 856 if (kCheckTransaction) { 857 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction()); 858 } 859 if (kVerifyFlags & kVerifyThis) { 860 VerifyObject(this); 861 } 862 if (kVerifyFlags & kVerifyWrites) { 863 VerifyObject(new_value); 864 } 865 if (kVerifyFlags & kVerifyReads) { 866 VerifyObject(old_value); 867 } 868 if (kTransactionActive) { 869 Runtime::Current()->RecordWriteFieldReference(this, field_offset, old_value, true); 870 } 871 uint32_t old_ref(PtrCompression<kPoisonHeapReferences, Object>::Compress(old_value)); 872 uint32_t new_ref(PtrCompression<kPoisonHeapReferences, Object>::Compress(new_value)); 873 uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value(); 874 Atomic<uint32_t>* atomic_addr = reinterpret_cast<Atomic<uint32_t>*>(raw_addr); 875 876 bool success = atomic_addr->CompareAndSetStrongSequentiallyConsistent(old_ref, new_ref); 877 return success; 878} 879 880template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> 881inline bool Object::CasFieldWeakRelaxedObjectWithoutWriteBarrier( 882 MemberOffset field_offset, 883 ObjPtr<Object> old_value, 884 ObjPtr<Object> new_value) { 885 if (kCheckTransaction) { 886 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction()); 887 } 888 if (kVerifyFlags & kVerifyThis) { 889 VerifyObject(this); 890 } 891 if (kVerifyFlags & kVerifyWrites) { 892 VerifyObject(new_value); 893 } 894 if (kVerifyFlags & kVerifyReads) { 895 VerifyObject(old_value); 896 } 897 if (kTransactionActive) { 898 Runtime::Current()->RecordWriteFieldReference(this, field_offset, old_value, true); 899 } 900 uint32_t old_ref(PtrCompression<kPoisonHeapReferences, Object>::Compress(old_value)); 901 uint32_t new_ref(PtrCompression<kPoisonHeapReferences, Object>::Compress(new_value)); 902 uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value(); 903 Atomic<uint32_t>* atomic_addr = reinterpret_cast<Atomic<uint32_t>*>(raw_addr); 904 905 bool success = atomic_addr->CompareAndSetWeakRelaxed(old_ref, new_ref); 906 return success; 907} 908 909template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> 910inline bool Object::CasFieldWeakReleaseObjectWithoutWriteBarrier( 911 MemberOffset field_offset, 912 ObjPtr<Object> old_value, 913 ObjPtr<Object> new_value) { 914 if (kCheckTransaction) { 915 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction()); 916 } 917 if (kVerifyFlags & kVerifyThis) { 918 VerifyObject(this); 919 } 920 if (kVerifyFlags & kVerifyWrites) { 921 VerifyObject(new_value); 922 } 923 if (kVerifyFlags & kVerifyReads) { 924 VerifyObject(old_value); 925 } 926 if (kTransactionActive) { 927 Runtime::Current()->RecordWriteFieldReference(this, field_offset, old_value, true); 928 } 929 uint32_t old_ref(PtrCompression<kPoisonHeapReferences, Object>::Compress(old_value)); 930 uint32_t new_ref(PtrCompression<kPoisonHeapReferences, Object>::Compress(new_value)); 931 uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value(); 932 Atomic<uint32_t>* atomic_addr = reinterpret_cast<Atomic<uint32_t>*>(raw_addr); 933 934 bool success = atomic_addr->CompareAndSetWeakRelease(old_ref, new_ref); 935 return success; 936} 937 938template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> 939inline ObjPtr<Object> Object::CompareAndExchangeFieldObject(MemberOffset field_offset, 940 ObjPtr<Object> old_value, 941 ObjPtr<Object> new_value) { 942 if (kCheckTransaction) { 943 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction()); 944 } 945 if (kVerifyFlags & kVerifyThis) { 946 VerifyObject(this); 947 } 948 if (kVerifyFlags & kVerifyWrites) { 949 VerifyObject(new_value); 950 } 951 if (kVerifyFlags & kVerifyReads) { 952 VerifyObject(old_value); 953 } 954 uint32_t old_ref(PtrCompression<kPoisonHeapReferences, Object>::Compress(old_value)); 955 uint32_t new_ref(PtrCompression<kPoisonHeapReferences, Object>::Compress(new_value)); 956 uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value(); 957 Atomic<uint32_t>* atomic_addr = reinterpret_cast<Atomic<uint32_t>*>(raw_addr); 958 bool success = atomic_addr->CompareAndExchangeStrongSequentiallyConsistent(&old_ref, new_ref); 959 ObjPtr<Object> witness_value(PtrCompression<kPoisonHeapReferences, Object>::Decompress(old_ref)); 960 if (kIsDebugBuild) { 961 // Ensure caller has done read barrier on the reference field so it's in the to-space. 962 ReadBarrier::AssertToSpaceInvariant(witness_value.Ptr()); 963 } 964 if (kTransactionActive && success) { 965 Runtime::Current()->RecordWriteFieldReference(this, field_offset, witness_value, true); 966 } 967 if (kVerifyFlags & kVerifyReads) { 968 VerifyObject(witness_value); 969 } 970 return witness_value; 971} 972 973template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> 974inline ObjPtr<Object> Object::ExchangeFieldObject(MemberOffset field_offset, 975 ObjPtr<Object> new_value) { 976 if (kCheckTransaction) { 977 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction()); 978 } 979 if (kVerifyFlags & kVerifyThis) { 980 VerifyObject(this); 981 } 982 if (kVerifyFlags & kVerifyWrites) { 983 VerifyObject(new_value); 984 } 985 uint32_t new_ref(PtrCompression<kPoisonHeapReferences, Object>::Compress(new_value)); 986 uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value(); 987 Atomic<uint32_t>* atomic_addr = reinterpret_cast<Atomic<uint32_t>*>(raw_addr); 988 uint32_t old_ref = atomic_addr->ExchangeSequentiallyConsistent(new_ref); 989 ObjPtr<Object> old_value(PtrCompression<kPoisonHeapReferences, Object>::Decompress(old_ref)); 990 if (kIsDebugBuild) { 991 // Ensure caller has done read barrier on the reference field so it's in the to-space. 992 ReadBarrier::AssertToSpaceInvariant(old_value.Ptr()); 993 } 994 if (kTransactionActive) { 995 Runtime::Current()->RecordWriteFieldReference(this, field_offset, old_value, true); 996 } 997 if (kVerifyFlags & kVerifyReads) { 998 VerifyObject(old_value); 999 } 1000 return old_value; 1001} 1002 1003template<typename T, VerifyObjectFlags kVerifyFlags> 1004inline void Object::GetPrimitiveFieldViaAccessor(MemberOffset field_offset, Accessor<T>* accessor) { 1005 if (kVerifyFlags & kVerifyThis) { 1006 VerifyObject(this); 1007 } 1008 uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value(); 1009 T* addr = reinterpret_cast<T*>(raw_addr); 1010 accessor->Access(addr); 1011} 1012 1013template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> 1014inline void Object::UpdateFieldBooleanViaAccessor(MemberOffset field_offset, 1015 Accessor<uint8_t>* accessor) { 1016 if (kCheckTransaction) { 1017 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction()); 1018 } 1019 if (kTransactionActive) { 1020 static const bool kIsVolatile = true; 1021 uint8_t old_value = GetFieldBoolean<kVerifyFlags, kIsVolatile>(field_offset); 1022 Runtime::Current()->RecordWriteFieldBoolean(this, field_offset, old_value, kIsVolatile); 1023 } 1024 if (kVerifyFlags & kVerifyThis) { 1025 VerifyObject(this); 1026 } 1027 uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value(); 1028 uint8_t* addr = raw_addr; 1029 accessor->Access(addr); 1030} 1031 1032template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> 1033inline void Object::UpdateFieldByteViaAccessor(MemberOffset field_offset, 1034 Accessor<int8_t>* accessor) { 1035 if (kCheckTransaction) { 1036 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction()); 1037 } 1038 if (kTransactionActive) { 1039 static const bool kIsVolatile = true; 1040 int8_t old_value = GetFieldByte<kVerifyFlags, kIsVolatile>(field_offset); 1041 Runtime::Current()->RecordWriteFieldByte(this, field_offset, old_value, kIsVolatile); 1042 } 1043 if (kVerifyFlags & kVerifyThis) { 1044 VerifyObject(this); 1045 } 1046 uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value(); 1047 int8_t* addr = reinterpret_cast<int8_t*>(raw_addr); 1048 accessor->Access(addr); 1049} 1050 1051template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> 1052inline void Object::UpdateFieldCharViaAccessor(MemberOffset field_offset, 1053 Accessor<uint16_t>* accessor) { 1054 if (kCheckTransaction) { 1055 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction()); 1056 } 1057 if (kTransactionActive) { 1058 static const bool kIsVolatile = true; 1059 uint16_t old_value = GetFieldChar<kVerifyFlags, kIsVolatile>(field_offset); 1060 Runtime::Current()->RecordWriteFieldChar(this, field_offset, old_value, kIsVolatile); 1061 } 1062 if (kVerifyFlags & kVerifyThis) { 1063 VerifyObject(this); 1064 } 1065 uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value(); 1066 uint16_t* addr = reinterpret_cast<uint16_t*>(raw_addr); 1067 accessor->Access(addr); 1068} 1069 1070template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> 1071inline void Object::UpdateFieldShortViaAccessor(MemberOffset field_offset, 1072 Accessor<int16_t>* accessor) { 1073 if (kCheckTransaction) { 1074 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction()); 1075 } 1076 if (kTransactionActive) { 1077 static const bool kIsVolatile = true; 1078 int16_t old_value = GetFieldShort<kVerifyFlags, kIsVolatile>(field_offset); 1079 Runtime::Current()->RecordWriteFieldShort(this, field_offset, old_value, kIsVolatile); 1080 } 1081 if (kVerifyFlags & kVerifyThis) { 1082 VerifyObject(this); 1083 } 1084 uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value(); 1085 int16_t* addr = reinterpret_cast<int16_t*>(raw_addr); 1086 accessor->Access(addr); 1087} 1088 1089template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> 1090inline void Object::UpdateField32ViaAccessor(MemberOffset field_offset, 1091 Accessor<int32_t>* accessor) { 1092 if (kCheckTransaction) { 1093 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction()); 1094 } 1095 if (kTransactionActive) { 1096 static const bool kIsVolatile = true; 1097 int32_t old_value = GetField32<kVerifyFlags, kIsVolatile>(field_offset); 1098 Runtime::Current()->RecordWriteField32(this, field_offset, old_value, kIsVolatile); 1099 } 1100 if (kVerifyFlags & kVerifyThis) { 1101 VerifyObject(this); 1102 } 1103 uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value(); 1104 int32_t* addr = reinterpret_cast<int32_t*>(raw_addr); 1105 accessor->Access(addr); 1106} 1107 1108template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> 1109inline void Object::UpdateField64ViaAccessor(MemberOffset field_offset, 1110 Accessor<int64_t>* accessor) { 1111 if (kCheckTransaction) { 1112 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction()); 1113 } 1114 if (kTransactionActive) { 1115 static const bool kIsVolatile = true; 1116 int64_t old_value = GetField64<kVerifyFlags, kIsVolatile>(field_offset); 1117 Runtime::Current()->RecordWriteField64(this, field_offset, old_value, kIsVolatile); 1118 } 1119 if (kVerifyFlags & kVerifyThis) { 1120 VerifyObject(this); 1121 } 1122 uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value(); 1123 int64_t* addr = reinterpret_cast<int64_t*>(raw_addr); 1124 accessor->Access(addr); 1125} 1126 1127template<bool kIsStatic, 1128 VerifyObjectFlags kVerifyFlags, 1129 ReadBarrierOption kReadBarrierOption, 1130 typename Visitor> 1131inline void Object::VisitFieldsReferences(uint32_t ref_offsets, const Visitor& visitor) { 1132 if (!kIsStatic && (ref_offsets != mirror::Class::kClassWalkSuper)) { 1133 // Instance fields and not the slow-path. 1134 uint32_t field_offset = mirror::kObjectHeaderSize; 1135 while (ref_offsets != 0) { 1136 if ((ref_offsets & 1) != 0) { 1137 visitor(this, MemberOffset(field_offset), kIsStatic); 1138 } 1139 ref_offsets >>= 1; 1140 field_offset += sizeof(mirror::HeapReference<mirror::Object>); 1141 } 1142 } else { 1143 // There is no reference offset bitmap. In the non-static case, walk up the class 1144 // inheritance hierarchy and find reference offsets the hard way. In the static case, just 1145 // consider this class. 1146 for (ObjPtr<Class> klass = kIsStatic 1147 ? AsClass<kVerifyFlags, kReadBarrierOption>() 1148 : GetClass<kVerifyFlags, kReadBarrierOption>(); 1149 klass != nullptr; 1150 klass = kIsStatic ? nullptr : klass->GetSuperClass<kVerifyFlags, kReadBarrierOption>()) { 1151 const size_t num_reference_fields = 1152 kIsStatic ? klass->NumReferenceStaticFields() : klass->NumReferenceInstanceFields(); 1153 if (num_reference_fields == 0u) { 1154 continue; 1155 } 1156 // Presumably GC can happen when we are cross compiling, it should not cause performance 1157 // problems to do pointer size logic. 1158 MemberOffset field_offset = kIsStatic 1159 ? klass->GetFirstReferenceStaticFieldOffset<kVerifyFlags, kReadBarrierOption>( 1160 Runtime::Current()->GetClassLinker()->GetImagePointerSize()) 1161 : klass->GetFirstReferenceInstanceFieldOffset<kVerifyFlags, kReadBarrierOption>(); 1162 for (size_t i = 0u; i < num_reference_fields; ++i) { 1163 // TODO: Do a simpler check? 1164 if (field_offset.Uint32Value() != ClassOffset().Uint32Value()) { 1165 visitor(this, field_offset, kIsStatic); 1166 } 1167 field_offset = MemberOffset(field_offset.Uint32Value() + 1168 sizeof(mirror::HeapReference<mirror::Object>)); 1169 } 1170 } 1171 } 1172} 1173 1174template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption, typename Visitor> 1175inline void Object::VisitInstanceFieldsReferences(ObjPtr<Class> klass, const Visitor& visitor) { 1176 VisitFieldsReferences<false, kVerifyFlags, kReadBarrierOption>( 1177 klass->GetReferenceInstanceOffsets<kVerifyFlags>(), visitor); 1178} 1179 1180template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption, typename Visitor> 1181inline void Object::VisitStaticFieldsReferences(ObjPtr<Class> klass, const Visitor& visitor) { 1182 DCHECK(!klass->IsTemp()); 1183 klass->VisitFieldsReferences<true, kVerifyFlags, kReadBarrierOption>(0, visitor); 1184} 1185 1186template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption> 1187inline bool Object::IsClassLoader() { 1188 return GetClass<kVerifyFlags, kReadBarrierOption>()->IsClassLoaderClass(); 1189} 1190 1191template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption> 1192inline mirror::ClassLoader* Object::AsClassLoader() { 1193 DCHECK((IsClassLoader<kVerifyFlags, kReadBarrierOption>())); 1194 return down_cast<mirror::ClassLoader*>(this); 1195} 1196 1197template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption> 1198inline bool Object::IsDexCache() { 1199 return GetClass<kVerifyFlags, kReadBarrierOption>()->IsDexCacheClass(); 1200} 1201 1202template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption> 1203inline mirror::DexCache* Object::AsDexCache() { 1204 DCHECK((IsDexCache<kVerifyFlags, kReadBarrierOption>())); 1205 return down_cast<mirror::DexCache*>(this); 1206} 1207 1208} // namespace mirror 1209} // namespace art 1210 1211#endif // ART_RUNTIME_MIRROR_OBJECT_INL_H_ 1212