1 /* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef ART_RUNTIME_MIRROR_OBJECT_INL_H_ 18 #define ART_RUNTIME_MIRROR_OBJECT_INL_H_ 19 20 #include "object.h" 21 22 #include "art_field.h" 23 #include "art_method.h" 24 #include "atomic.h" 25 #include "array-inl.h" 26 #include "class-inl.h" 27 #include "class_flags.h" 28 #include "class_linker.h" 29 #include "class_loader-inl.h" 30 #include "dex_cache-inl.h" 31 #include "lock_word-inl.h" 32 #include "monitor.h" 33 #include "object_array-inl.h" 34 #include "object_reference-inl.h" 35 #include "object-readbarrier-inl.h" 36 #include "obj_ptr-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 return klass->IsAssignableFrom(GetClass<kVerifyFlags>()); 165 } 166 167 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption> 168 inline 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 175 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption> 176 inline Class* Object::AsClass() { 177 DCHECK((IsClass<kVerifyFlags, kReadBarrierOption>())); 178 return down_cast<Class*>(this); 179 } 180 181 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption> 182 inline 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 189 template<class T, VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption> 190 inline ObjectArray<T>* Object::AsObjectArray() { 191 DCHECK((IsObjectArray<kVerifyFlags, kReadBarrierOption>())); 192 return down_cast<ObjectArray<T>*>(this); 193 } 194 195 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption> 196 inline bool Object::IsArrayInstance() { 197 return GetClass<kVerifyFlags, kReadBarrierOption>()-> 198 template IsArrayClass<kVerifyFlags, kReadBarrierOption>(); 199 } 200 201 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption> 202 inline bool Object::IsReferenceInstance() { 203 return GetClass<kVerifyFlags, kReadBarrierOption>()->IsTypeOfReferenceClass(); 204 } 205 206 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption> 207 inline Reference* Object::AsReference() { 208 DCHECK((IsReferenceInstance<kVerifyFlags, kReadBarrierOption>())); 209 return down_cast<Reference*>(this); 210 } 211 212 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption> 213 inline Array* Object::AsArray() { 214 DCHECK((IsArrayInstance<kVerifyFlags, kReadBarrierOption>())); 215 return down_cast<Array*>(this); 216 } 217 218 template<VerifyObjectFlags kVerifyFlags> 219 inline 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 226 template<VerifyObjectFlags kVerifyFlags> 227 inline 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 234 template<VerifyObjectFlags kVerifyFlags> 235 inline 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 243 template<VerifyObjectFlags kVerifyFlags> 244 inline 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 251 template<VerifyObjectFlags kVerifyFlags> 252 inline 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 259 template<VerifyObjectFlags kVerifyFlags> 260 inline 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 268 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption> 269 inline 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 276 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption> 277 inline IntArray* Object::AsIntArray() { 278 DCHECK((IsIntArray<kVerifyFlags, kReadBarrierOption>())); 279 return down_cast<IntArray*>(this); 280 } 281 282 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption> 283 inline 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 290 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption> 291 inline LongArray* Object::AsLongArray() { 292 DCHECK((IsLongArray<kVerifyFlags, kReadBarrierOption>())); 293 return down_cast<LongArray*>(this); 294 } 295 296 template<VerifyObjectFlags kVerifyFlags> 297 inline 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 303 template<VerifyObjectFlags kVerifyFlags> 304 inline 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 312 template<VerifyObjectFlags kVerifyFlags> 313 inline 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 319 template<VerifyObjectFlags kVerifyFlags> 320 inline 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 328 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption> 329 inline bool Object::IsString() { 330 return GetClass<kVerifyFlags, kReadBarrierOption>()->IsStringClass(); 331 } 332 333 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption> 334 inline String* Object::AsString() { 335 DCHECK((IsString<kVerifyFlags, kReadBarrierOption>())); 336 return down_cast<String*>(this); 337 } 338 339 template<VerifyObjectFlags kVerifyFlags> 340 inline Throwable* Object::AsThrowable() { 341 DCHECK(GetClass<kVerifyFlags>()->IsThrowableClass()); 342 return down_cast<Throwable*>(this); 343 } 344 345 template<VerifyObjectFlags kVerifyFlags> 346 inline bool Object::IsWeakReferenceInstance() { 347 return GetClass<kVerifyFlags>()->IsWeakReferenceClass(); 348 } 349 350 template<VerifyObjectFlags kVerifyFlags> 351 inline bool Object::IsSoftReferenceInstance() { 352 return GetClass<kVerifyFlags>()->IsSoftReferenceClass(); 353 } 354 355 template<VerifyObjectFlags kVerifyFlags> 356 inline bool Object::IsFinalizerReferenceInstance() { 357 return GetClass<kVerifyFlags>()->IsFinalizerReferenceClass(); 358 } 359 360 template<VerifyObjectFlags kVerifyFlags> 361 inline FinalizerReference* Object::AsFinalizerReference() { 362 DCHECK(IsFinalizerReferenceInstance<kVerifyFlags>()); 363 return down_cast<FinalizerReference*>(this); 364 } 365 366 template<VerifyObjectFlags kVerifyFlags> 367 inline bool Object::IsPhantomReferenceInstance() { 368 return GetClass<kVerifyFlags>()->IsPhantomReferenceClass(); 369 } 370 371 template<VerifyObjectFlags kVerifyFlags> 372 inline 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 396 template<VerifyObjectFlags kVerifyFlags, bool kIsVolatile> 397 inline uint8_t Object::GetFieldBoolean(MemberOffset field_offset) { 398 if (kVerifyFlags & kVerifyThis) { 399 VerifyObject(this); 400 } 401 return GetField<uint8_t, kIsVolatile>(field_offset); 402 } 403 404 template<VerifyObjectFlags kVerifyFlags, bool kIsVolatile> 405 inline int8_t Object::GetFieldByte(MemberOffset field_offset) { 406 if (kVerifyFlags & kVerifyThis) { 407 VerifyObject(this); 408 } 409 return GetField<int8_t, kIsVolatile>(field_offset); 410 } 411 412 template<VerifyObjectFlags kVerifyFlags> 413 inline uint8_t Object::GetFieldBooleanVolatile(MemberOffset field_offset) { 414 return GetFieldBoolean<kVerifyFlags, true>(field_offset); 415 } 416 417 template<VerifyObjectFlags kVerifyFlags> 418 inline int8_t Object::GetFieldByteVolatile(MemberOffset field_offset) { 419 return GetFieldByte<kVerifyFlags, true>(field_offset); 420 } 421 422 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags, 423 bool kIsVolatile> 424 inline void Object::SetFieldBoolean(MemberOffset field_offset, uint8_t new_value) 425 REQUIRES_SHARED(Locks::mutator_lock_) { 426 if (kCheckTransaction) { 427 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction()); 428 } 429 if (kTransactionActive) { 430 Runtime::Current()->RecordWriteFieldBoolean(this, field_offset, 431 GetFieldBoolean<kVerifyFlags, kIsVolatile>(field_offset), 432 kIsVolatile); 433 } 434 if (kVerifyFlags & kVerifyThis) { 435 VerifyObject(this); 436 } 437 SetField<uint8_t, kIsVolatile>(field_offset, new_value); 438 } 439 440 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags, 441 bool kIsVolatile> 442 inline void Object::SetFieldByte(MemberOffset field_offset, int8_t new_value) 443 REQUIRES_SHARED(Locks::mutator_lock_) { 444 if (kCheckTransaction) { 445 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction()); 446 } 447 if (kTransactionActive) { 448 Runtime::Current()->RecordWriteFieldByte(this, field_offset, 449 GetFieldByte<kVerifyFlags, kIsVolatile>(field_offset), 450 kIsVolatile); 451 } 452 if (kVerifyFlags & kVerifyThis) { 453 VerifyObject(this); 454 } 455 SetField<int8_t, kIsVolatile>(field_offset, new_value); 456 } 457 458 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> 459 inline void Object::SetFieldBooleanVolatile(MemberOffset field_offset, uint8_t new_value) { 460 return SetFieldBoolean<kTransactionActive, kCheckTransaction, kVerifyFlags, true>( 461 field_offset, new_value); 462 } 463 464 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> 465 inline void Object::SetFieldByteVolatile(MemberOffset field_offset, int8_t new_value) { 466 return SetFieldByte<kTransactionActive, kCheckTransaction, kVerifyFlags, true>( 467 field_offset, new_value); 468 } 469 470 template<VerifyObjectFlags kVerifyFlags, bool kIsVolatile> 471 inline uint16_t Object::GetFieldChar(MemberOffset field_offset) { 472 if (kVerifyFlags & kVerifyThis) { 473 VerifyObject(this); 474 } 475 return GetField<uint16_t, kIsVolatile>(field_offset); 476 } 477 478 template<VerifyObjectFlags kVerifyFlags, bool kIsVolatile> 479 inline int16_t Object::GetFieldShort(MemberOffset field_offset) { 480 if (kVerifyFlags & kVerifyThis) { 481 VerifyObject(this); 482 } 483 return GetField<int16_t, kIsVolatile>(field_offset); 484 } 485 486 template<VerifyObjectFlags kVerifyFlags> 487 inline uint16_t Object::GetFieldCharVolatile(MemberOffset field_offset) { 488 return GetFieldChar<kVerifyFlags, true>(field_offset); 489 } 490 491 template<VerifyObjectFlags kVerifyFlags> 492 inline int16_t Object::GetFieldShortVolatile(MemberOffset field_offset) { 493 return GetFieldShort<kVerifyFlags, true>(field_offset); 494 } 495 496 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags, 497 bool kIsVolatile> 498 inline void Object::SetFieldChar(MemberOffset field_offset, uint16_t new_value) { 499 if (kCheckTransaction) { 500 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction()); 501 } 502 if (kTransactionActive) { 503 Runtime::Current()->RecordWriteFieldChar(this, field_offset, 504 GetFieldChar<kVerifyFlags, kIsVolatile>(field_offset), 505 kIsVolatile); 506 } 507 if (kVerifyFlags & kVerifyThis) { 508 VerifyObject(this); 509 } 510 SetField<uint16_t, kIsVolatile>(field_offset, new_value); 511 } 512 513 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags, 514 bool kIsVolatile> 515 inline void Object::SetFieldShort(MemberOffset field_offset, int16_t new_value) { 516 if (kCheckTransaction) { 517 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction()); 518 } 519 if (kTransactionActive) { 520 Runtime::Current()->RecordWriteFieldChar(this, field_offset, 521 GetFieldShort<kVerifyFlags, kIsVolatile>(field_offset), 522 kIsVolatile); 523 } 524 if (kVerifyFlags & kVerifyThis) { 525 VerifyObject(this); 526 } 527 SetField<int16_t, kIsVolatile>(field_offset, new_value); 528 } 529 530 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> 531 inline void Object::SetFieldCharVolatile(MemberOffset field_offset, uint16_t new_value) { 532 return SetFieldChar<kTransactionActive, kCheckTransaction, kVerifyFlags, true>( 533 field_offset, new_value); 534 } 535 536 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> 537 inline void Object::SetFieldShortVolatile(MemberOffset field_offset, int16_t new_value) { 538 return SetFieldShort<kTransactionActive, kCheckTransaction, kVerifyFlags, true>( 539 field_offset, new_value); 540 } 541 542 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags, 543 bool kIsVolatile> 544 inline void Object::SetField32(MemberOffset field_offset, int32_t new_value) { 545 if (kCheckTransaction) { 546 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction()); 547 } 548 if (kTransactionActive) { 549 Runtime::Current()->RecordWriteField32(this, field_offset, 550 GetField32<kVerifyFlags, kIsVolatile>(field_offset), 551 kIsVolatile); 552 } 553 if (kVerifyFlags & kVerifyThis) { 554 VerifyObject(this); 555 } 556 SetField<int32_t, kIsVolatile>(field_offset, new_value); 557 } 558 559 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> 560 inline void Object::SetField32Volatile(MemberOffset field_offset, int32_t new_value) { 561 SetField32<kTransactionActive, kCheckTransaction, kVerifyFlags, true>(field_offset, new_value); 562 } 563 564 // TODO: Pass memory_order_ and strong/weak as arguments to avoid code duplication? 565 566 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> 567 inline bool Object::CasFieldWeakSequentiallyConsistent32(MemberOffset field_offset, 568 int32_t old_value, int32_t new_value) { 569 if (kCheckTransaction) { 570 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction()); 571 } 572 if (kTransactionActive) { 573 Runtime::Current()->RecordWriteField32(this, field_offset, old_value, true); 574 } 575 if (kVerifyFlags & kVerifyThis) { 576 VerifyObject(this); 577 } 578 uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value(); 579 AtomicInteger* atomic_addr = reinterpret_cast<AtomicInteger*>(raw_addr); 580 581 return atomic_addr->CompareExchangeWeakSequentiallyConsistent(old_value, new_value); 582 } 583 584 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> 585 inline bool Object::CasFieldWeakAcquire32(MemberOffset field_offset, 586 int32_t old_value, int32_t new_value) { 587 if (kCheckTransaction) { 588 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction()); 589 } 590 if (kTransactionActive) { 591 Runtime::Current()->RecordWriteField32(this, field_offset, old_value, true); 592 } 593 if (kVerifyFlags & kVerifyThis) { 594 VerifyObject(this); 595 } 596 uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value(); 597 AtomicInteger* atomic_addr = reinterpret_cast<AtomicInteger*>(raw_addr); 598 599 return atomic_addr->CompareExchangeWeakAcquire(old_value, new_value); 600 } 601 602 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> 603 inline bool Object::CasFieldWeakRelease32(MemberOffset field_offset, 604 int32_t old_value, int32_t new_value) { 605 if (kCheckTransaction) { 606 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction()); 607 } 608 if (kTransactionActive) { 609 Runtime::Current()->RecordWriteField32(this, field_offset, old_value, true); 610 } 611 if (kVerifyFlags & kVerifyThis) { 612 VerifyObject(this); 613 } 614 uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value(); 615 AtomicInteger* atomic_addr = reinterpret_cast<AtomicInteger*>(raw_addr); 616 617 return atomic_addr->CompareExchangeWeakRelease(old_value, new_value); 618 } 619 620 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> 621 inline bool Object::CasFieldStrongSequentiallyConsistent32(MemberOffset field_offset, 622 int32_t old_value, int32_t new_value) { 623 if (kCheckTransaction) { 624 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction()); 625 } 626 if (kTransactionActive) { 627 Runtime::Current()->RecordWriteField32(this, field_offset, old_value, true); 628 } 629 if (kVerifyFlags & kVerifyThis) { 630 VerifyObject(this); 631 } 632 uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value(); 633 AtomicInteger* atomic_addr = reinterpret_cast<AtomicInteger*>(raw_addr); 634 635 return atomic_addr->CompareExchangeStrongSequentiallyConsistent(old_value, new_value); 636 } 637 638 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags, 639 bool kIsVolatile> 640 inline void Object::SetField64(MemberOffset field_offset, int64_t new_value) { 641 if (kCheckTransaction) { 642 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction()); 643 } 644 if (kTransactionActive) { 645 Runtime::Current()->RecordWriteField64(this, field_offset, 646 GetField64<kVerifyFlags, kIsVolatile>(field_offset), 647 kIsVolatile); 648 } 649 if (kVerifyFlags & kVerifyThis) { 650 VerifyObject(this); 651 } 652 SetField<int64_t, kIsVolatile>(field_offset, new_value); 653 } 654 655 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> 656 inline void Object::SetField64Volatile(MemberOffset field_offset, int64_t new_value) { 657 return SetField64<kTransactionActive, kCheckTransaction, kVerifyFlags, true>(field_offset, 658 new_value); 659 } 660 661 template<typename kSize> 662 inline kSize Object::GetFieldAcquire(MemberOffset field_offset) { 663 const uint8_t* raw_addr = reinterpret_cast<const uint8_t*>(this) + field_offset.Int32Value(); 664 const kSize* addr = reinterpret_cast<const kSize*>(raw_addr); 665 return reinterpret_cast<const Atomic<kSize>*>(addr)->LoadAcquire(); 666 } 667 668 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> 669 inline bool Object::CasFieldWeakSequentiallyConsistent64(MemberOffset field_offset, 670 int64_t old_value, int64_t new_value) { 671 if (kCheckTransaction) { 672 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction()); 673 } 674 if (kTransactionActive) { 675 Runtime::Current()->RecordWriteField64(this, field_offset, old_value, true); 676 } 677 if (kVerifyFlags & kVerifyThis) { 678 VerifyObject(this); 679 } 680 uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value(); 681 Atomic<int64_t>* atomic_addr = reinterpret_cast<Atomic<int64_t>*>(raw_addr); 682 return atomic_addr->CompareExchangeWeakSequentiallyConsistent(old_value, new_value); 683 } 684 685 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> 686 inline bool Object::CasFieldStrongSequentiallyConsistent64(MemberOffset field_offset, 687 int64_t old_value, int64_t new_value) { 688 if (kCheckTransaction) { 689 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction()); 690 } 691 if (kTransactionActive) { 692 Runtime::Current()->RecordWriteField64(this, field_offset, old_value, true); 693 } 694 if (kVerifyFlags & kVerifyThis) { 695 VerifyObject(this); 696 } 697 uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value(); 698 Atomic<int64_t>* atomic_addr = reinterpret_cast<Atomic<int64_t>*>(raw_addr); 699 return atomic_addr->CompareExchangeStrongSequentiallyConsistent(old_value, new_value); 700 } 701 702 template<class T, VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption, 703 bool kIsVolatile> 704 inline T* Object::GetFieldObject(MemberOffset field_offset) { 705 if (kVerifyFlags & kVerifyThis) { 706 VerifyObject(this); 707 } 708 uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value(); 709 HeapReference<T>* objref_addr = reinterpret_cast<HeapReference<T>*>(raw_addr); 710 T* result = ReadBarrier::Barrier<T, kReadBarrierOption>(this, field_offset, objref_addr); 711 if (kIsVolatile) { 712 // TODO: Refactor to use a SequentiallyConsistent load instead. 713 QuasiAtomic::ThreadFenceAcquire(); // Ensure visibility of operations preceding store. 714 } 715 if (kVerifyFlags & kVerifyReads) { 716 VerifyObject(result); 717 } 718 return result; 719 } 720 721 template<class T, VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption> 722 inline T* Object::GetFieldObjectVolatile(MemberOffset field_offset) { 723 return GetFieldObject<T, kVerifyFlags, kReadBarrierOption, true>(field_offset); 724 } 725 726 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags, 727 bool kIsVolatile> 728 inline void Object::SetFieldObjectWithoutWriteBarrier(MemberOffset field_offset, 729 ObjPtr<Object> new_value) { 730 if (kCheckTransaction) { 731 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction()); 732 } 733 if (kTransactionActive) { 734 ObjPtr<Object> obj; 735 if (kIsVolatile) { 736 obj = GetFieldObjectVolatile<Object>(field_offset); 737 } else { 738 obj = GetFieldObject<Object>(field_offset); 739 } 740 Runtime::Current()->RecordWriteFieldReference(this, field_offset, obj.Ptr(), true); 741 } 742 if (kVerifyFlags & kVerifyThis) { 743 VerifyObject(this); 744 } 745 if (kVerifyFlags & kVerifyWrites) { 746 VerifyObject(new_value); 747 } 748 uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value(); 749 HeapReference<Object>* objref_addr = reinterpret_cast<HeapReference<Object>*>(raw_addr); 750 if (kIsVolatile) { 751 // TODO: Refactor to use a SequentiallyConsistent store instead. 752 QuasiAtomic::ThreadFenceRelease(); // Ensure that prior accesses are visible before store. 753 objref_addr->Assign(new_value.Ptr()); 754 QuasiAtomic::ThreadFenceSequentiallyConsistent(); 755 // Ensure this store occurs before any volatile loads. 756 } else { 757 objref_addr->Assign(new_value.Ptr()); 758 } 759 } 760 761 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags, 762 bool kIsVolatile> 763 inline void Object::SetFieldObject(MemberOffset field_offset, ObjPtr<Object> new_value) { 764 SetFieldObjectWithoutWriteBarrier<kTransactionActive, kCheckTransaction, kVerifyFlags, 765 kIsVolatile>(field_offset, new_value); 766 if (new_value != nullptr) { 767 Runtime::Current()->GetHeap()->WriteBarrierField(this, field_offset, new_value); 768 // TODO: Check field assignment could theoretically cause thread suspension, TODO: fix this. 769 CheckFieldAssignment(field_offset, new_value); 770 } 771 } 772 773 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> 774 inline void Object::SetFieldObjectVolatile(MemberOffset field_offset, ObjPtr<Object> new_value) { 775 SetFieldObject<kTransactionActive, kCheckTransaction, kVerifyFlags, true>(field_offset, 776 new_value); 777 } 778 779 template <VerifyObjectFlags kVerifyFlags> 780 inline HeapReference<Object>* Object::GetFieldObjectReferenceAddr(MemberOffset field_offset) { 781 if (kVerifyFlags & kVerifyThis) { 782 VerifyObject(this); 783 } 784 return reinterpret_cast<HeapReference<Object>*>(reinterpret_cast<uint8_t*>(this) + 785 field_offset.Int32Value()); 786 } 787 788 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> 789 inline bool Object::CasFieldWeakSequentiallyConsistentObject(MemberOffset field_offset, 790 ObjPtr<Object> old_value, 791 ObjPtr<Object> new_value) { 792 bool success = CasFieldWeakSequentiallyConsistentObjectWithoutWriteBarrier< 793 kTransactionActive, kCheckTransaction, kVerifyFlags>(field_offset, old_value, new_value); 794 if (success) { 795 Runtime::Current()->GetHeap()->WriteBarrierField(this, field_offset, new_value); 796 } 797 return success; 798 } 799 800 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> 801 inline bool Object::CasFieldWeakSequentiallyConsistentObjectWithoutWriteBarrier( 802 MemberOffset field_offset, 803 ObjPtr<Object> old_value, 804 ObjPtr<Object> new_value) { 805 if (kCheckTransaction) { 806 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction()); 807 } 808 if (kVerifyFlags & kVerifyThis) { 809 VerifyObject(this); 810 } 811 if (kVerifyFlags & kVerifyWrites) { 812 VerifyObject(new_value); 813 } 814 if (kVerifyFlags & kVerifyReads) { 815 VerifyObject(old_value); 816 } 817 if (kTransactionActive) { 818 Runtime::Current()->RecordWriteFieldReference(this, field_offset, old_value, true); 819 } 820 HeapReference<Object> old_ref(HeapReference<Object>::FromObjPtr(old_value)); 821 HeapReference<Object> new_ref(HeapReference<Object>::FromObjPtr(new_value)); 822 uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value(); 823 Atomic<uint32_t>* atomic_addr = reinterpret_cast<Atomic<uint32_t>*>(raw_addr); 824 825 bool success = atomic_addr->CompareExchangeWeakSequentiallyConsistent(old_ref.reference_, 826 new_ref.reference_); 827 return success; 828 } 829 830 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> 831 inline bool Object::CasFieldStrongSequentiallyConsistentObject(MemberOffset field_offset, 832 ObjPtr<Object> old_value, 833 ObjPtr<Object> new_value) { 834 bool success = CasFieldStrongSequentiallyConsistentObjectWithoutWriteBarrier< 835 kTransactionActive, kCheckTransaction, kVerifyFlags>(field_offset, old_value, new_value); 836 if (success) { 837 Runtime::Current()->GetHeap()->WriteBarrierField(this, field_offset, new_value); 838 } 839 return success; 840 } 841 842 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> 843 inline bool Object::CasFieldStrongSequentiallyConsistentObjectWithoutWriteBarrier( 844 MemberOffset field_offset, 845 ObjPtr<Object> old_value, 846 ObjPtr<Object> new_value) { 847 if (kCheckTransaction) { 848 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction()); 849 } 850 if (kVerifyFlags & kVerifyThis) { 851 VerifyObject(this); 852 } 853 if (kVerifyFlags & kVerifyWrites) { 854 VerifyObject(new_value); 855 } 856 if (kVerifyFlags & kVerifyReads) { 857 VerifyObject(old_value); 858 } 859 if (kTransactionActive) { 860 Runtime::Current()->RecordWriteFieldReference(this, field_offset, old_value, true); 861 } 862 HeapReference<Object> old_ref(HeapReference<Object>::FromObjPtr(old_value)); 863 HeapReference<Object> new_ref(HeapReference<Object>::FromObjPtr(new_value)); 864 uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value(); 865 Atomic<uint32_t>* atomic_addr = reinterpret_cast<Atomic<uint32_t>*>(raw_addr); 866 867 bool success = atomic_addr->CompareExchangeStrongSequentiallyConsistent(old_ref.reference_, 868 new_ref.reference_); 869 return success; 870 } 871 872 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> 873 inline bool Object::CasFieldWeakRelaxedObjectWithoutWriteBarrier( 874 MemberOffset field_offset, 875 ObjPtr<Object> old_value, 876 ObjPtr<Object> new_value) { 877 if (kCheckTransaction) { 878 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction()); 879 } 880 if (kVerifyFlags & kVerifyThis) { 881 VerifyObject(this); 882 } 883 if (kVerifyFlags & kVerifyWrites) { 884 VerifyObject(new_value); 885 } 886 if (kVerifyFlags & kVerifyReads) { 887 VerifyObject(old_value); 888 } 889 if (kTransactionActive) { 890 Runtime::Current()->RecordWriteFieldReference(this, field_offset, old_value, true); 891 } 892 HeapReference<Object> old_ref(HeapReference<Object>::FromObjPtr(old_value)); 893 HeapReference<Object> new_ref(HeapReference<Object>::FromObjPtr(new_value)); 894 uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value(); 895 Atomic<uint32_t>* atomic_addr = reinterpret_cast<Atomic<uint32_t>*>(raw_addr); 896 897 bool success = atomic_addr->CompareExchangeWeakRelaxed(old_ref.reference_, 898 new_ref.reference_); 899 return success; 900 } 901 902 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> 903 inline bool Object::CasFieldWeakReleaseObjectWithoutWriteBarrier( 904 MemberOffset field_offset, 905 ObjPtr<Object> old_value, 906 ObjPtr<Object> new_value) { 907 if (kCheckTransaction) { 908 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction()); 909 } 910 if (kVerifyFlags & kVerifyThis) { 911 VerifyObject(this); 912 } 913 if (kVerifyFlags & kVerifyWrites) { 914 VerifyObject(new_value); 915 } 916 if (kVerifyFlags & kVerifyReads) { 917 VerifyObject(old_value); 918 } 919 if (kTransactionActive) { 920 Runtime::Current()->RecordWriteFieldReference(this, field_offset, old_value, true); 921 } 922 HeapReference<Object> old_ref(HeapReference<Object>::FromObjPtr(old_value)); 923 HeapReference<Object> new_ref(HeapReference<Object>::FromObjPtr(new_value)); 924 uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value(); 925 Atomic<uint32_t>* atomic_addr = reinterpret_cast<Atomic<uint32_t>*>(raw_addr); 926 927 bool success = atomic_addr->CompareExchangeWeakRelease(old_ref.reference_, 928 new_ref.reference_); 929 return success; 930 } 931 932 template<bool kIsStatic, 933 VerifyObjectFlags kVerifyFlags, 934 ReadBarrierOption kReadBarrierOption, 935 typename Visitor> 936 inline void Object::VisitFieldsReferences(uint32_t ref_offsets, const Visitor& visitor) { 937 if (!kIsStatic && (ref_offsets != mirror::Class::kClassWalkSuper)) { 938 // Instance fields and not the slow-path. 939 uint32_t field_offset = mirror::kObjectHeaderSize; 940 while (ref_offsets != 0) { 941 if ((ref_offsets & 1) != 0) { 942 visitor(this, MemberOffset(field_offset), kIsStatic); 943 } 944 ref_offsets >>= 1; 945 field_offset += sizeof(mirror::HeapReference<mirror::Object>); 946 } 947 } else { 948 // There is no reference offset bitmap. In the non-static case, walk up the class 949 // inheritance hierarchy and find reference offsets the hard way. In the static case, just 950 // consider this class. 951 for (ObjPtr<Class> klass = kIsStatic 952 ? AsClass<kVerifyFlags, kReadBarrierOption>() 953 : GetClass<kVerifyFlags, kReadBarrierOption>(); 954 klass != nullptr; 955 klass = kIsStatic ? nullptr : klass->GetSuperClass<kVerifyFlags, kReadBarrierOption>()) { 956 const size_t num_reference_fields = 957 kIsStatic ? klass->NumReferenceStaticFields() : klass->NumReferenceInstanceFields(); 958 if (num_reference_fields == 0u) { 959 continue; 960 } 961 // Presumably GC can happen when we are cross compiling, it should not cause performance 962 // problems to do pointer size logic. 963 MemberOffset field_offset = kIsStatic 964 ? klass->GetFirstReferenceStaticFieldOffset<kVerifyFlags, kReadBarrierOption>( 965 Runtime::Current()->GetClassLinker()->GetImagePointerSize()) 966 : klass->GetFirstReferenceInstanceFieldOffset<kVerifyFlags, kReadBarrierOption>(); 967 for (size_t i = 0u; i < num_reference_fields; ++i) { 968 // TODO: Do a simpler check? 969 if (field_offset.Uint32Value() != ClassOffset().Uint32Value()) { 970 visitor(this, field_offset, kIsStatic); 971 } 972 field_offset = MemberOffset(field_offset.Uint32Value() + 973 sizeof(mirror::HeapReference<mirror::Object>)); 974 } 975 } 976 } 977 } 978 979 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption, typename Visitor> 980 inline void Object::VisitInstanceFieldsReferences(ObjPtr<Class> klass, const Visitor& visitor) { 981 VisitFieldsReferences<false, kVerifyFlags, kReadBarrierOption>( 982 klass->GetReferenceInstanceOffsets<kVerifyFlags>(), visitor); 983 } 984 985 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption, typename Visitor> 986 inline void Object::VisitStaticFieldsReferences(ObjPtr<Class> klass, const Visitor& visitor) { 987 DCHECK(!klass->IsTemp()); 988 klass->VisitFieldsReferences<true, kVerifyFlags, kReadBarrierOption>(0, visitor); 989 } 990 991 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption> 992 inline bool Object::IsClassLoader() { 993 return GetClass<kVerifyFlags, kReadBarrierOption>()->IsClassLoaderClass(); 994 } 995 996 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption> 997 inline mirror::ClassLoader* Object::AsClassLoader() { 998 DCHECK((IsClassLoader<kVerifyFlags, kReadBarrierOption>())); 999 return down_cast<mirror::ClassLoader*>(this); 1000 } 1001 1002 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption> 1003 inline bool Object::IsDexCache() { 1004 return GetClass<kVerifyFlags, kReadBarrierOption>()->IsDexCacheClass(); 1005 } 1006 1007 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption> 1008 inline mirror::DexCache* Object::AsDexCache() { 1009 DCHECK((IsDexCache<kVerifyFlags, kReadBarrierOption>())); 1010 return down_cast<mirror::DexCache*>(this); 1011 } 1012 1013 } // namespace mirror 1014 } // namespace art 1015 1016 #endif // ART_RUNTIME_MIRROR_OBJECT_INL_H_ 1017