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