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.h" 41 #include "throwable.h" 42 #include "write_barrier-inl.h" 43 44 namespace art { 45 namespace mirror { 46 ClassSize(PointerSize pointer_size)47 inline uint32_t Object::ClassSize(PointerSize pointer_size) { 48 uint32_t vtable_entries = kVTableLength; 49 return Class::ComputeClassSize(true, vtable_entries, 0, 0, 0, 0, 0, pointer_size); 50 } 51 52 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption> GetClass()53 inline Class* Object::GetClass() { 54 return GetFieldObject<Class, kVerifyFlags, kReadBarrierOption>(ClassOffset()); 55 } 56 57 template<VerifyObjectFlags kVerifyFlags> SetClass(ObjPtr<Class> new_klass)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, RemoveThisFlags(kVerifyFlags)>(ClassOffset(), 65 new_klass); 66 } 67 68 template<VerifyObjectFlags kVerifyFlags> SetLockWord(LockWord new_val,bool as_volatile)69 inline void Object::SetLockWord(LockWord new_val, bool as_volatile) { 70 // Force use of non-transactional mode and do not check. 71 if (as_volatile) { 72 SetField32Volatile<false, false, kVerifyFlags>(MonitorOffset(), new_val.GetValue()); 73 } else { 74 SetField32<false, false, kVerifyFlags>(MonitorOffset(), new_val.GetValue()); 75 } 76 } 77 GetLockOwnerThreadId()78 inline uint32_t Object::GetLockOwnerThreadId() { 79 return Monitor::GetLockOwnerThreadId(this); 80 } 81 MonitorEnter(Thread * self)82 inline ObjPtr<mirror::Object> Object::MonitorEnter(Thread* self) { 83 return Monitor::MonitorEnter(self, this, /*trylock=*/false); 84 } 85 MonitorTryEnter(Thread * self)86 inline ObjPtr<mirror::Object> Object::MonitorTryEnter(Thread* self) { 87 return Monitor::MonitorEnter(self, this, /*trylock=*/true); 88 } 89 MonitorExit(Thread * self)90 inline bool Object::MonitorExit(Thread* self) { 91 return Monitor::MonitorExit(self, this); 92 } 93 Notify(Thread * self)94 inline void Object::Notify(Thread* self) { 95 Monitor::Notify(self, this); 96 } 97 NotifyAll(Thread * self)98 inline void Object::NotifyAll(Thread* self) { 99 Monitor::NotifyAll(self, this); 100 } 101 Wait(Thread * self,int64_t ms,int32_t ns)102 inline void Object::Wait(Thread* self, int64_t ms, int32_t ns) { 103 Monitor::Wait(self, this, ms, ns, true, ThreadState::kTimedWaiting); 104 } 105 GetMarkBit()106 inline uint32_t Object::GetMarkBit() { 107 CHECK(gUseReadBarrier); 108 return GetLockWord(false).MarkBitState(); 109 } 110 SetReadBarrierState(uint32_t rb_state)111 inline void Object::SetReadBarrierState(uint32_t rb_state) { 112 CHECK(kUseBakerReadBarrier); 113 DCHECK(ReadBarrier::IsValidReadBarrierState(rb_state)) << rb_state; 114 LockWord lw = GetLockWord(false); 115 lw.SetReadBarrierState(rb_state); 116 SetLockWord(lw, false); 117 } 118 AssertReadBarrierState()119 inline void Object::AssertReadBarrierState() const { 120 CHECK(kUseBakerReadBarrier); 121 Object* obj = const_cast<Object*>(this); 122 DCHECK_EQ(obj->GetReadBarrierState(), ReadBarrier::NonGrayState()) 123 << "Bad Baker pointer: obj=" << obj << " rb_state" << obj->GetReadBarrierState(); 124 } 125 126 template<VerifyObjectFlags kVerifyFlags> VerifierInstanceOf(ObjPtr<Class> klass)127 inline bool Object::VerifierInstanceOf(ObjPtr<Class> klass) { 128 DCHECK(klass != nullptr); 129 DCHECK(GetClass<kVerifyFlags>() != nullptr); 130 return klass->IsInterface() || InstanceOf(klass); 131 } 132 133 template<VerifyObjectFlags kVerifyFlags> InstanceOf(ObjPtr<Class> klass)134 inline bool Object::InstanceOf(ObjPtr<Class> klass) { 135 DCHECK(klass != nullptr); 136 DCHECK(GetClass<kVerifyNone>() != nullptr) << "this=" << this; 137 return klass->IsAssignableFrom(GetClass<kVerifyFlags>()); 138 } 139 140 template<VerifyObjectFlags kVerifyFlags> IsClass()141 inline bool Object::IsClass() { 142 // OK to look at from-space copies since java.lang.Class.class is non-moveable 143 // (even when running without boot image, see ClassLinker::InitWithoutImage()) 144 // and we're reading constant references for comparison only. See ReadBarrierOption. 145 ObjPtr<Class> klass = GetClass<kVerifyFlags, kWithoutReadBarrier>(); 146 ObjPtr<Class> java_lang_Class = klass->GetClass<kVerifyFlags, kWithoutReadBarrier>(); 147 return klass == java_lang_Class; 148 } 149 150 template<VerifyObjectFlags kVerifyFlags> AsClass()151 inline ObjPtr<Class> Object::AsClass() { 152 DCHECK((IsClass<kVerifyFlags>())); 153 return ObjPtr<Class>::DownCast(this); 154 } 155 156 template<VerifyObjectFlags kVerifyFlags> IsObjectArray()157 inline bool Object::IsObjectArray() { 158 // We do not need a read barrier here as the primitive type is constant, 159 // both from-space and to-space component type classes shall yield the same result. 160 constexpr VerifyObjectFlags kNewFlags = RemoveThisFlags(kVerifyFlags); 161 return IsArrayInstance<kVerifyFlags>() && 162 !GetClass<kNewFlags, kWithoutReadBarrier>()-> 163 template GetComponentType<kNewFlags, kWithoutReadBarrier>()->IsPrimitive(); 164 } 165 166 template<class T, VerifyObjectFlags kVerifyFlags> AsObjectArray()167 inline ObjPtr<ObjectArray<T>> Object::AsObjectArray() { 168 DCHECK((IsObjectArray<kVerifyFlags>())); 169 return ObjPtr<ObjectArray<T>>::DownCast(this); 170 } 171 172 template<VerifyObjectFlags kVerifyFlags> IsArrayInstance()173 inline bool Object::IsArrayInstance() { 174 // We do not need a read barrier here, both from-space and to-space version of the class 175 // shall return the same result from IsArrayClass(). 176 return GetClass<kVerifyFlags, kWithoutReadBarrier>()->template IsArrayClass<kVerifyFlags>(); 177 } 178 179 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption> IsReferenceInstance()180 inline bool Object::IsReferenceInstance() { 181 return GetClass<kVerifyFlags, kReadBarrierOption>()->IsTypeOfReferenceClass(); 182 } 183 184 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption> AsReference()185 inline ObjPtr<Reference> Object::AsReference() { 186 DCHECK((IsReferenceInstance<kVerifyFlags, kReadBarrierOption>())); 187 return ObjPtr<Reference>::DownCast(this); 188 } 189 190 template<VerifyObjectFlags kVerifyFlags> AsArray()191 inline ObjPtr<Array> Object::AsArray() { 192 DCHECK((IsArrayInstance<kVerifyFlags>())); 193 return ObjPtr<Array>::DownCast(this); 194 } 195 196 template<VerifyObjectFlags kVerifyFlags, Primitive::Type kType> IsSpecificPrimitiveArray()197 ALWAYS_INLINE bool Object::IsSpecificPrimitiveArray() { 198 // We do not need a read barrier here as the primitive type is constant, both from-space 199 // and to-space component type classes shall yield the same result. See ReadBarrierOption. 200 const ObjPtr<Class> klass = GetClass<kVerifyFlags, kWithoutReadBarrier>(); 201 constexpr VerifyObjectFlags kNewFlags = RemoveThisFlags(kVerifyFlags); 202 const ObjPtr<Class> component_type = klass->GetComponentType<kNewFlags, kWithoutReadBarrier>(); 203 return component_type != nullptr && 204 component_type->GetPrimitiveType<kNewFlags>() == kType; 205 } 206 207 template<VerifyObjectFlags kVerifyFlags> IsBooleanArray()208 inline bool Object::IsBooleanArray() { 209 return IsSpecificPrimitiveArray<kVerifyFlags, Primitive::kPrimBoolean>(); 210 } 211 212 template<VerifyObjectFlags kVerifyFlags> AsBooleanArray()213 inline ObjPtr<BooleanArray> Object::AsBooleanArray() { 214 DCHECK(IsBooleanArray<kVerifyFlags>()); 215 return ObjPtr<BooleanArray>::DownCast(this); 216 } 217 218 template<VerifyObjectFlags kVerifyFlags> IsByteArray()219 inline bool Object::IsByteArray() { 220 return IsSpecificPrimitiveArray<kVerifyFlags, Primitive::kPrimByte>(); 221 } 222 223 template<VerifyObjectFlags kVerifyFlags> AsByteArray()224 inline ObjPtr<ByteArray> Object::AsByteArray() { 225 DCHECK(IsByteArray<kVerifyFlags>()); 226 return ObjPtr<ByteArray>::DownCast(this); 227 } 228 229 template<VerifyObjectFlags kVerifyFlags> IsCharArray()230 inline bool Object::IsCharArray() { 231 return IsSpecificPrimitiveArray<kVerifyFlags, Primitive::kPrimChar>(); 232 } 233 234 template<VerifyObjectFlags kVerifyFlags> AsCharArray()235 inline ObjPtr<CharArray> Object::AsCharArray() { 236 DCHECK(IsCharArray<kVerifyFlags>()); 237 return ObjPtr<CharArray>::DownCast(this); 238 } 239 240 template<VerifyObjectFlags kVerifyFlags> IsShortArray()241 inline bool Object::IsShortArray() { 242 return IsSpecificPrimitiveArray<kVerifyFlags, Primitive::kPrimShort>(); 243 } 244 245 template<VerifyObjectFlags kVerifyFlags> AsShortArray()246 inline ObjPtr<ShortArray> Object::AsShortArray() { 247 DCHECK(IsShortArray<kVerifyFlags>()); 248 return ObjPtr<ShortArray>::DownCast(this); 249 } 250 251 template<VerifyObjectFlags kVerifyFlags> IsIntArray()252 inline bool Object::IsIntArray() { 253 return IsSpecificPrimitiveArray<kVerifyFlags, Primitive::kPrimInt>(); 254 } 255 256 template<VerifyObjectFlags kVerifyFlags> AsIntArrayUnchecked()257 inline ObjPtr<IntArray> Object::AsIntArrayUnchecked() { 258 return ObjPtr<IntArray>::DownCast(this); 259 } 260 template<VerifyObjectFlags kVerifyFlags> AsIntArray()261 inline ObjPtr<IntArray> Object::AsIntArray() { 262 DCHECK((IsIntArray<kVerifyFlags>())); 263 return AsIntArrayUnchecked<kVerifyFlags>(); 264 } 265 266 template<VerifyObjectFlags kVerifyFlags> IsLongArray()267 inline bool Object::IsLongArray() { 268 return IsSpecificPrimitiveArray<kVerifyFlags, Primitive::kPrimLong>(); 269 } 270 271 template<VerifyObjectFlags kVerifyFlags> AsLongArrayUnchecked()272 inline ObjPtr<LongArray> Object::AsLongArrayUnchecked() { 273 return ObjPtr<LongArray>::DownCast(this); 274 } 275 template<VerifyObjectFlags kVerifyFlags> AsLongArray()276 inline ObjPtr<LongArray> Object::AsLongArray() { 277 DCHECK((IsLongArray<kVerifyFlags>())); 278 return AsLongArrayUnchecked<kVerifyFlags>(); 279 } 280 281 template<VerifyObjectFlags kVerifyFlags> IsFloatArray()282 inline bool Object::IsFloatArray() { 283 return IsSpecificPrimitiveArray<kVerifyFlags, Primitive::kPrimFloat>(); 284 } 285 286 template<VerifyObjectFlags kVerifyFlags> AsFloatArray()287 inline ObjPtr<FloatArray> Object::AsFloatArray() { 288 DCHECK(IsFloatArray<kVerifyFlags>()); 289 return ObjPtr<FloatArray>::DownCast(this); 290 } 291 292 template<VerifyObjectFlags kVerifyFlags> IsDoubleArray()293 inline bool Object::IsDoubleArray() { 294 return IsSpecificPrimitiveArray<kVerifyFlags, Primitive::kPrimDouble>(); 295 } 296 297 template<VerifyObjectFlags kVerifyFlags> AsDoubleArray()298 inline ObjPtr<DoubleArray> Object::AsDoubleArray() { 299 DCHECK(IsDoubleArray<kVerifyFlags>()); 300 return ObjPtr<DoubleArray>::DownCast(this); 301 } 302 303 template<VerifyObjectFlags kVerifyFlags> IsString()304 inline bool Object::IsString() { 305 // No read barrier is needed for reading a constant primitive field through 306 // constant reference field. See ReadBarrierOption. 307 return GetClass<kVerifyFlags, kWithoutReadBarrier>()->IsStringClass(); 308 } 309 310 template<VerifyObjectFlags kVerifyFlags> AsString()311 inline ObjPtr<String> Object::AsString() { 312 DCHECK((IsString<kVerifyFlags>())); 313 return ObjPtr<String>::DownCast(this); 314 } 315 316 template<VerifyObjectFlags kVerifyFlags> AsThrowable()317 inline ObjPtr<Throwable> Object::AsThrowable() { 318 DCHECK(GetClass<kVerifyFlags>()->IsThrowableClass()); 319 return ObjPtr<Throwable>::DownCast(this); 320 } 321 322 template<VerifyObjectFlags kVerifyFlags> IsWeakReferenceInstance()323 inline bool Object::IsWeakReferenceInstance() { 324 return GetClass<kVerifyFlags>()->IsWeakReferenceClass(); 325 } 326 327 template<VerifyObjectFlags kVerifyFlags> IsSoftReferenceInstance()328 inline bool Object::IsSoftReferenceInstance() { 329 return GetClass<kVerifyFlags>()->IsSoftReferenceClass(); 330 } 331 332 template<VerifyObjectFlags kVerifyFlags> IsFinalizerReferenceInstance()333 inline bool Object::IsFinalizerReferenceInstance() { 334 return GetClass<kVerifyFlags>()->IsFinalizerReferenceClass(); 335 } 336 337 template<VerifyObjectFlags kVerifyFlags> AsFinalizerReference()338 inline ObjPtr<FinalizerReference> Object::AsFinalizerReference() { 339 DCHECK(IsFinalizerReferenceInstance<kVerifyFlags>()); 340 return ObjPtr<FinalizerReference>::DownCast(this); 341 } 342 343 template<VerifyObjectFlags kVerifyFlags> IsPhantomReferenceInstance()344 inline bool Object::IsPhantomReferenceInstance() { 345 return GetClass<kVerifyFlags>()->IsPhantomReferenceClass(); 346 } 347 348 template<VerifyObjectFlags kVerifyFlags> SizeOf()349 inline size_t Object::SizeOf() { 350 // Read barrier is never required for SizeOf since objects sizes are constant. Reading from-space 351 // values is OK because of that. 352 size_t result; 353 constexpr VerifyObjectFlags kNewFlags = RemoveThisFlags(kVerifyFlags); 354 if (IsArrayInstance<kVerifyFlags>()) { 355 result = AsArray<kNewFlags>()->template SizeOf<kNewFlags>(); 356 } else if (IsClass<kNewFlags>()) { 357 result = AsClass<kNewFlags>()->template SizeOf<kNewFlags>(); 358 } else if (IsString<kNewFlags>()) { 359 result = AsString<kNewFlags>()->template SizeOf<kNewFlags>(); 360 } else { 361 result = GetClass<kNewFlags, kWithoutReadBarrier>()->template GetObjectSize<kNewFlags>(); 362 } 363 DCHECK_GE(result, sizeof(Object)) << " class=" 364 // Note: Class::PrettyClass() is reading constant reference fields to get to constant 365 // primitive fields and safely avoids read barriers, so it is safe to call on a Class 366 // reference read without read barrier from a constant reference field. 367 // See ReadBarrierOption. And, for correctness, we actually have to avoid the read 368 // barrier here if Object::SizeOf() is called on a from-space reference. 369 << GetClass<kNewFlags, kWithoutReadBarrier>()->PrettyClass(); 370 return result; 371 } 372 373 template<VerifyObjectFlags kVerifyFlags, bool kIsVolatile> GetFieldByte(MemberOffset field_offset)374 inline int8_t Object::GetFieldByte(MemberOffset field_offset) { 375 Verify<kVerifyFlags>(); 376 return GetFieldPrimitive<int8_t, kIsVolatile>(field_offset); 377 } 378 379 template<VerifyObjectFlags kVerifyFlags> GetFieldBooleanVolatile(MemberOffset field_offset)380 inline uint8_t Object::GetFieldBooleanVolatile(MemberOffset field_offset) { 381 return GetFieldBoolean<kVerifyFlags, true>(field_offset); 382 } 383 384 template<VerifyObjectFlags kVerifyFlags> GetFieldByteVolatile(MemberOffset field_offset)385 inline int8_t Object::GetFieldByteVolatile(MemberOffset field_offset) { 386 return GetFieldByte<kVerifyFlags, true>(field_offset); 387 } 388 389 template<bool kTransactionActive, 390 bool kCheckTransaction, 391 VerifyObjectFlags kVerifyFlags, 392 bool kIsVolatile> SetFieldBoolean(MemberOffset field_offset,uint8_t new_value)393 inline void Object::SetFieldBoolean(MemberOffset field_offset, uint8_t new_value) { 394 VerifyTransaction<kTransactionActive, kCheckTransaction>(); 395 if (kTransactionActive) { 396 Runtime::Current()->RecordWriteFieldBoolean( 397 this, 398 field_offset, 399 GetFieldBoolean<kVerifyFlags, kIsVolatile>(field_offset), 400 kIsVolatile); 401 } 402 Verify<kVerifyFlags>(); 403 SetFieldPrimitive<uint8_t, kIsVolatile>(field_offset, new_value); 404 } 405 406 template<bool kTransactionActive, 407 bool kCheckTransaction, 408 VerifyObjectFlags kVerifyFlags, 409 bool kIsVolatile> SetFieldByte(MemberOffset field_offset,int8_t new_value)410 inline void Object::SetFieldByte(MemberOffset field_offset, int8_t new_value) { 411 VerifyTransaction<kTransactionActive, kCheckTransaction>(); 412 if (kTransactionActive) { 413 Runtime::Current()->RecordWriteFieldByte(this, 414 field_offset, 415 GetFieldByte<kVerifyFlags, kIsVolatile>(field_offset), 416 kIsVolatile); 417 } 418 Verify<kVerifyFlags>(); 419 SetFieldPrimitive<int8_t, kIsVolatile>(field_offset, new_value); 420 } 421 422 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> SetFieldBooleanVolatile(MemberOffset field_offset,uint8_t new_value)423 inline void Object::SetFieldBooleanVolatile(MemberOffset field_offset, uint8_t new_value) { 424 return SetFieldBoolean<kTransactionActive, kCheckTransaction, kVerifyFlags, true>( 425 field_offset, new_value); 426 } 427 428 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> SetFieldByteVolatile(MemberOffset field_offset,int8_t new_value)429 inline void Object::SetFieldByteVolatile(MemberOffset field_offset, int8_t new_value) { 430 return SetFieldByte<kTransactionActive, kCheckTransaction, kVerifyFlags, true>( 431 field_offset, new_value); 432 } 433 434 template<VerifyObjectFlags kVerifyFlags, bool kIsVolatile> GetFieldChar(MemberOffset field_offset)435 inline uint16_t Object::GetFieldChar(MemberOffset field_offset) { 436 Verify<kVerifyFlags>(); 437 return GetFieldPrimitive<uint16_t, kIsVolatile>(field_offset); 438 } 439 440 template<VerifyObjectFlags kVerifyFlags, bool kIsVolatile> GetFieldShort(MemberOffset field_offset)441 inline int16_t Object::GetFieldShort(MemberOffset field_offset) { 442 Verify<kVerifyFlags>(); 443 return GetFieldPrimitive<int16_t, kIsVolatile>(field_offset); 444 } 445 446 template<VerifyObjectFlags kVerifyFlags> GetFieldCharVolatile(MemberOffset field_offset)447 inline uint16_t Object::GetFieldCharVolatile(MemberOffset field_offset) { 448 return GetFieldChar<kVerifyFlags, true>(field_offset); 449 } 450 451 template<VerifyObjectFlags kVerifyFlags> GetFieldShortVolatile(MemberOffset field_offset)452 inline int16_t Object::GetFieldShortVolatile(MemberOffset field_offset) { 453 return GetFieldShort<kVerifyFlags, true>(field_offset); 454 } 455 456 template<bool kTransactionActive, 457 bool kCheckTransaction, 458 VerifyObjectFlags kVerifyFlags, 459 bool kIsVolatile> SetFieldChar(MemberOffset field_offset,uint16_t new_value)460 inline void Object::SetFieldChar(MemberOffset field_offset, uint16_t new_value) { 461 VerifyTransaction<kTransactionActive, kCheckTransaction>(); 462 if (kTransactionActive) { 463 Runtime::Current()->RecordWriteFieldChar(this, 464 field_offset, 465 GetFieldChar<kVerifyFlags, kIsVolatile>(field_offset), 466 kIsVolatile); 467 } 468 Verify<kVerifyFlags>(); 469 SetFieldPrimitive<uint16_t, kIsVolatile>(field_offset, new_value); 470 } 471 472 template<bool kTransactionActive, 473 bool kCheckTransaction, 474 VerifyObjectFlags kVerifyFlags, 475 bool kIsVolatile> SetFieldShort(MemberOffset field_offset,int16_t new_value)476 inline void Object::SetFieldShort(MemberOffset field_offset, int16_t new_value) { 477 VerifyTransaction<kTransactionActive, kCheckTransaction>(); 478 if (kTransactionActive) { 479 Runtime::Current()->RecordWriteFieldChar(this, 480 field_offset, 481 GetFieldShort<kVerifyFlags, kIsVolatile>(field_offset), 482 kIsVolatile); 483 } 484 Verify<kVerifyFlags>(); 485 SetFieldPrimitive<int16_t, kIsVolatile>(field_offset, new_value); 486 } 487 488 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> SetFieldCharVolatile(MemberOffset field_offset,uint16_t new_value)489 inline void Object::SetFieldCharVolatile(MemberOffset field_offset, uint16_t new_value) { 490 return SetFieldChar<kTransactionActive, kCheckTransaction, kVerifyFlags, true>( 491 field_offset, new_value); 492 } 493 494 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> SetFieldShortVolatile(MemberOffset field_offset,int16_t new_value)495 inline void Object::SetFieldShortVolatile(MemberOffset field_offset, int16_t new_value) { 496 return SetFieldShort<kTransactionActive, kCheckTransaction, kVerifyFlags, true>( 497 field_offset, new_value); 498 } 499 500 template<bool kTransactionActive, 501 bool kCheckTransaction, 502 VerifyObjectFlags kVerifyFlags, 503 bool kIsVolatile> SetField32(MemberOffset field_offset,int32_t new_value)504 inline void Object::SetField32(MemberOffset field_offset, int32_t new_value) { 505 VerifyTransaction<kTransactionActive, kCheckTransaction>(); 506 if (kTransactionActive) { 507 Runtime::Current()->RecordWriteField32(this, 508 field_offset, 509 GetField32<kVerifyFlags, kIsVolatile>(field_offset), 510 kIsVolatile); 511 } 512 Verify<kVerifyFlags>(); 513 SetFieldPrimitive<int32_t, kIsVolatile>(field_offset, new_value); 514 } 515 516 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> SetField32Volatile(MemberOffset field_offset,int32_t new_value)517 inline void Object::SetField32Volatile(MemberOffset field_offset, int32_t new_value) { 518 SetField32<kTransactionActive, kCheckTransaction, kVerifyFlags, true>(field_offset, new_value); 519 } 520 521 template<bool kCheckTransaction, VerifyObjectFlags kVerifyFlags, bool kIsVolatile> SetField32Transaction(MemberOffset field_offset,int32_t new_value)522 inline void Object::SetField32Transaction(MemberOffset field_offset, int32_t new_value) { 523 if (Runtime::Current()->IsActiveTransaction()) { 524 SetField32<true, kCheckTransaction, kVerifyFlags, kIsVolatile>(field_offset, new_value); 525 } else { 526 SetField32<false, kCheckTransaction, kVerifyFlags, kIsVolatile>(field_offset, new_value); 527 } 528 } 529 530 template<bool kTransactionActive, 531 bool kCheckTransaction, 532 VerifyObjectFlags kVerifyFlags, 533 bool kIsVolatile> SetField64(MemberOffset field_offset,int64_t new_value)534 inline void Object::SetField64(MemberOffset field_offset, int64_t new_value) { 535 VerifyTransaction<kTransactionActive, kCheckTransaction>(); 536 if (kTransactionActive) { 537 Runtime::Current()->RecordWriteField64(this, 538 field_offset, 539 GetField64<kVerifyFlags, kIsVolatile>(field_offset), 540 kIsVolatile); 541 } 542 Verify<kVerifyFlags>(); 543 SetFieldPrimitive<int64_t, kIsVolatile>(field_offset, new_value); 544 } 545 546 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> SetField64Volatile(MemberOffset field_offset,int64_t new_value)547 inline void Object::SetField64Volatile(MemberOffset field_offset, int64_t new_value) { 548 return SetField64<kTransactionActive, kCheckTransaction, kVerifyFlags, true>(field_offset, 549 new_value); 550 } 551 552 template<bool kCheckTransaction, VerifyObjectFlags kVerifyFlags, bool kIsVolatile> SetField64Transaction(MemberOffset field_offset,int32_t new_value)553 inline void Object::SetField64Transaction(MemberOffset field_offset, int32_t new_value) { 554 if (Runtime::Current()->IsActiveTransaction()) { 555 SetField64<true, kCheckTransaction, kVerifyFlags, kIsVolatile>(field_offset, new_value); 556 } else { 557 SetField64<false, kCheckTransaction, kVerifyFlags, kIsVolatile>(field_offset, new_value); 558 } 559 } 560 561 template<typename kSize> GetFieldAcquire(MemberOffset field_offset)562 inline kSize Object::GetFieldAcquire(MemberOffset field_offset) { 563 const uint8_t* raw_addr = reinterpret_cast<const uint8_t*>(this) + field_offset.Int32Value(); 564 const kSize* addr = reinterpret_cast<const kSize*>(raw_addr); 565 return reinterpret_cast<const Atomic<kSize>*>(addr)->load(std::memory_order_acquire); 566 } 567 568 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> CasFieldWeakSequentiallyConsistent64(MemberOffset field_offset,int64_t old_value,int64_t new_value)569 inline bool Object::CasFieldWeakSequentiallyConsistent64(MemberOffset field_offset, 570 int64_t old_value, 571 int64_t new_value) { 572 VerifyTransaction<kTransactionActive, kCheckTransaction>(); 573 if (kTransactionActive) { 574 Runtime::Current()->RecordWriteField64(this, field_offset, old_value, true); 575 } 576 Verify<kVerifyFlags>(); 577 uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value(); 578 Atomic<int64_t>* atomic_addr = reinterpret_cast<Atomic<int64_t>*>(raw_addr); 579 return atomic_addr->CompareAndSetWeakSequentiallyConsistent(old_value, new_value); 580 } 581 582 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> CasFieldStrongSequentiallyConsistent64(MemberOffset field_offset,int64_t old_value,int64_t new_value)583 inline bool Object::CasFieldStrongSequentiallyConsistent64(MemberOffset field_offset, 584 int64_t old_value, 585 int64_t new_value) { 586 VerifyTransaction<kTransactionActive, kCheckTransaction>(); 587 if (kTransactionActive) { 588 Runtime::Current()->RecordWriteField64(this, field_offset, old_value, true); 589 } 590 Verify<kVerifyFlags>(); 591 uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value(); 592 Atomic<int64_t>* atomic_addr = reinterpret_cast<Atomic<int64_t>*>(raw_addr); 593 return atomic_addr->CompareAndSetStrongSequentiallyConsistent(old_value, new_value); 594 } 595 596 /* 597 * Returns a pointer to an object representing what the field points to, not an 598 * object representing the field. 599 */ 600 template<class T, 601 VerifyObjectFlags kVerifyFlags, 602 ReadBarrierOption kReadBarrierOption, 603 bool kIsVolatile> GetFieldObject(MemberOffset field_offset)604 inline T* Object::GetFieldObject(MemberOffset field_offset) { 605 Verify<kVerifyFlags>(); 606 uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value(); 607 HeapReference<T>* objref_addr = reinterpret_cast<HeapReference<T>*>(raw_addr); 608 T* result = ReadBarrier::Barrier<T, kIsVolatile, kReadBarrierOption>( 609 this, 610 field_offset, 611 objref_addr); 612 VerifyRead<kVerifyFlags>(result); 613 return result; 614 } 615 616 template<class T, VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption> GetFieldObjectVolatile(MemberOffset field_offset)617 inline T* Object::GetFieldObjectVolatile(MemberOffset field_offset) { 618 return GetFieldObject<T, kVerifyFlags, kReadBarrierOption, true>(field_offset); 619 } 620 621 template<bool kTransactionActive, 622 bool kCheckTransaction, 623 VerifyObjectFlags kVerifyFlags, 624 bool kIsVolatile> SetFieldObjectWithoutWriteBarrier(MemberOffset field_offset,ObjPtr<Object> new_value)625 inline void Object::SetFieldObjectWithoutWriteBarrier(MemberOffset field_offset, 626 ObjPtr<Object> new_value) { 627 VerifyTransaction<kTransactionActive, kCheckTransaction>(); 628 if (kTransactionActive) { 629 ObjPtr<Object> obj; 630 if (kIsVolatile) { 631 obj = GetFieldObjectVolatile<Object>(field_offset); 632 } else { 633 obj = GetFieldObject<Object>(field_offset); 634 } 635 Runtime::Current()->RecordWriteFieldReference(this, field_offset, obj, true); 636 } 637 Verify<kVerifyFlags>(); 638 VerifyWrite<kVerifyFlags>(new_value); 639 uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value(); 640 HeapReference<Object>* objref_addr = reinterpret_cast<HeapReference<Object>*>(raw_addr); 641 objref_addr->Assign<kIsVolatile>(new_value.Ptr()); 642 } 643 644 template<bool kTransactionActive, 645 bool kCheckTransaction, 646 VerifyObjectFlags kVerifyFlags, 647 bool kIsVolatile> SetFieldObject(MemberOffset field_offset,ObjPtr<Object> new_value)648 inline void Object::SetFieldObject(MemberOffset field_offset, ObjPtr<Object> new_value) { 649 SetFieldObjectWithoutWriteBarrier<kTransactionActive, kCheckTransaction, kVerifyFlags, 650 kIsVolatile>(field_offset, new_value); 651 if (new_value != nullptr) { 652 WriteBarrier::ForFieldWrite<WriteBarrier::kWithoutNullCheck>(this, field_offset, new_value); 653 // TODO: Check field assignment could theoretically cause thread suspension, TODO: fix this. 654 CheckFieldAssignment(field_offset, new_value); 655 } 656 } 657 658 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> SetFieldObjectVolatile(MemberOffset field_offset,ObjPtr<Object> new_value)659 inline void Object::SetFieldObjectVolatile(MemberOffset field_offset, ObjPtr<Object> new_value) { 660 SetFieldObject<kTransactionActive, kCheckTransaction, kVerifyFlags, true>(field_offset, 661 new_value); 662 } 663 664 template<bool kCheckTransaction, VerifyObjectFlags kVerifyFlags, bool kIsVolatile> SetFieldObjectTransaction(MemberOffset field_offset,ObjPtr<Object> new_value)665 inline void Object::SetFieldObjectTransaction(MemberOffset field_offset, ObjPtr<Object> new_value) { 666 if (Runtime::Current()->IsActiveTransaction()) { 667 SetFieldObject<true, kCheckTransaction, kVerifyFlags, kIsVolatile>(field_offset, new_value); 668 } else { 669 SetFieldObject<false, kCheckTransaction, kVerifyFlags, kIsVolatile>(field_offset, new_value); 670 } 671 } 672 673 template <VerifyObjectFlags kVerifyFlags> GetFieldObjectReferenceAddr(MemberOffset field_offset)674 inline HeapReference<Object>* Object::GetFieldObjectReferenceAddr(MemberOffset field_offset) { 675 Verify<kVerifyFlags>(); 676 return reinterpret_cast<HeapReference<Object>*>(reinterpret_cast<uint8_t*>(this) + 677 field_offset.Int32Value()); 678 } 679 680 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> CasFieldObjectWithoutWriteBarrier(MemberOffset field_offset,ObjPtr<Object> old_value,ObjPtr<Object> new_value,CASMode mode,std::memory_order memory_order)681 inline bool Object::CasFieldObjectWithoutWriteBarrier(MemberOffset field_offset, 682 ObjPtr<Object> old_value, 683 ObjPtr<Object> new_value, 684 CASMode mode, 685 std::memory_order memory_order) { 686 VerifyTransaction<kTransactionActive, kCheckTransaction>(); 687 VerifyCAS<kVerifyFlags>(new_value, old_value); 688 if (kTransactionActive) { 689 Runtime::Current()->RecordWriteFieldReference(this, field_offset, old_value, true); 690 } 691 uint32_t old_ref(PtrCompression<kPoisonHeapReferences, Object>::Compress(old_value)); 692 uint32_t new_ref(PtrCompression<kPoisonHeapReferences, Object>::Compress(new_value)); 693 uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value(); 694 Atomic<uint32_t>* atomic_addr = reinterpret_cast<Atomic<uint32_t>*>(raw_addr); 695 return atomic_addr->CompareAndSet(old_ref, new_ref, mode, memory_order); 696 } 697 698 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> CasFieldObject(MemberOffset field_offset,ObjPtr<Object> old_value,ObjPtr<Object> new_value,CASMode mode,std::memory_order memory_order)699 inline bool Object::CasFieldObject(MemberOffset field_offset, 700 ObjPtr<Object> old_value, 701 ObjPtr<Object> new_value, 702 CASMode mode, 703 std::memory_order memory_order) { 704 bool success = CasFieldObjectWithoutWriteBarrier< 705 kTransactionActive, kCheckTransaction, kVerifyFlags>(field_offset, 706 old_value, 707 new_value, 708 mode, 709 memory_order); 710 if (success) { 711 WriteBarrier::ForFieldWrite(this, field_offset, new_value); 712 } 713 return success; 714 } 715 716 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> CompareAndExchangeFieldObject(MemberOffset field_offset,ObjPtr<Object> old_value,ObjPtr<Object> new_value)717 inline ObjPtr<Object> Object::CompareAndExchangeFieldObject(MemberOffset field_offset, 718 ObjPtr<Object> old_value, 719 ObjPtr<Object> new_value) { 720 VerifyTransaction<kTransactionActive, kCheckTransaction>(); 721 VerifyCAS<kVerifyFlags>(new_value, old_value); 722 uint32_t old_ref(PtrCompression<kPoisonHeapReferences, Object>::Compress(old_value)); 723 uint32_t new_ref(PtrCompression<kPoisonHeapReferences, Object>::Compress(new_value)); 724 uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value(); 725 Atomic<uint32_t>* atomic_addr = reinterpret_cast<Atomic<uint32_t>*>(raw_addr); 726 bool success = atomic_addr->compare_exchange_strong(old_ref, new_ref, std::memory_order_seq_cst); 727 ObjPtr<Object> witness_value(PtrCompression<kPoisonHeapReferences, Object>::Decompress(old_ref)); 728 if (kIsDebugBuild) { 729 // Ensure caller has done read barrier on the reference field so it's in the to-space. 730 ReadBarrier::AssertToSpaceInvariant(witness_value.Ptr()); 731 } 732 if (success) { 733 if (kTransactionActive) { 734 Runtime::Current()->RecordWriteFieldReference(this, field_offset, witness_value, true); 735 } 736 WriteBarrier::ForFieldWrite(this, field_offset, new_value); 737 } 738 VerifyRead<kVerifyFlags>(witness_value); 739 return witness_value; 740 } 741 742 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> ExchangeFieldObject(MemberOffset field_offset,ObjPtr<Object> new_value)743 inline ObjPtr<Object> Object::ExchangeFieldObject(MemberOffset field_offset, 744 ObjPtr<Object> new_value) { 745 VerifyTransaction<kTransactionActive, kCheckTransaction>(); 746 VerifyCAS<kVerifyFlags>(new_value, /*old_value=*/ nullptr); 747 748 uint32_t new_ref(PtrCompression<kPoisonHeapReferences, Object>::Compress(new_value)); 749 uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value(); 750 Atomic<uint32_t>* atomic_addr = reinterpret_cast<Atomic<uint32_t>*>(raw_addr); 751 uint32_t old_ref = atomic_addr->exchange(new_ref, std::memory_order_seq_cst); 752 ObjPtr<Object> old_value(PtrCompression<kPoisonHeapReferences, Object>::Decompress(old_ref)); 753 if (kIsDebugBuild) { 754 // Ensure caller has done read barrier on the reference field so it's in the to-space. 755 ReadBarrier::AssertToSpaceInvariant(old_value.Ptr()); 756 } 757 if (kTransactionActive) { 758 Runtime::Current()->RecordWriteFieldReference(this, field_offset, old_value, true); 759 } 760 WriteBarrier::ForFieldWrite(this, field_offset, new_value); 761 VerifyRead<kVerifyFlags>(old_value); 762 return old_value; 763 } 764 765 template<typename T, VerifyObjectFlags kVerifyFlags> GetPrimitiveFieldViaAccessor(MemberOffset field_offset,Accessor<T> * accessor)766 inline void Object::GetPrimitiveFieldViaAccessor(MemberOffset field_offset, Accessor<T>* accessor) { 767 Verify<kVerifyFlags>(); 768 uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value(); 769 T* addr = reinterpret_cast<T*>(raw_addr); 770 accessor->Access(addr); 771 } 772 773 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> UpdateFieldBooleanViaAccessor(MemberOffset field_offset,Accessor<uint8_t> * accessor)774 inline void Object::UpdateFieldBooleanViaAccessor(MemberOffset field_offset, 775 Accessor<uint8_t>* accessor) { 776 VerifyTransaction<kTransactionActive, kCheckTransaction>(); 777 if (kTransactionActive) { 778 static const bool kIsVolatile = true; 779 uint8_t old_value = GetFieldBoolean<kVerifyFlags, kIsVolatile>(field_offset); 780 Runtime::Current()->RecordWriteFieldBoolean(this, field_offset, old_value, kIsVolatile); 781 } 782 Verify<kVerifyFlags>(); 783 uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value(); 784 uint8_t* addr = raw_addr; 785 accessor->Access(addr); 786 } 787 788 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> UpdateFieldByteViaAccessor(MemberOffset field_offset,Accessor<int8_t> * accessor)789 inline void Object::UpdateFieldByteViaAccessor(MemberOffset field_offset, 790 Accessor<int8_t>* accessor) { 791 VerifyTransaction<kTransactionActive, kCheckTransaction>(); 792 if (kTransactionActive) { 793 static const bool kIsVolatile = true; 794 int8_t old_value = GetFieldByte<kVerifyFlags, kIsVolatile>(field_offset); 795 Runtime::Current()->RecordWriteFieldByte(this, field_offset, old_value, kIsVolatile); 796 } 797 Verify<kVerifyFlags>(); 798 uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value(); 799 int8_t* addr = reinterpret_cast<int8_t*>(raw_addr); 800 accessor->Access(addr); 801 } 802 803 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> UpdateFieldCharViaAccessor(MemberOffset field_offset,Accessor<uint16_t> * accessor)804 inline void Object::UpdateFieldCharViaAccessor(MemberOffset field_offset, 805 Accessor<uint16_t>* accessor) { 806 VerifyTransaction<kTransactionActive, kCheckTransaction>(); 807 if (kTransactionActive) { 808 static const bool kIsVolatile = true; 809 uint16_t old_value = GetFieldChar<kVerifyFlags, kIsVolatile>(field_offset); 810 Runtime::Current()->RecordWriteFieldChar(this, field_offset, old_value, kIsVolatile); 811 } 812 Verify<kVerifyFlags>(); 813 uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value(); 814 uint16_t* addr = reinterpret_cast<uint16_t*>(raw_addr); 815 accessor->Access(addr); 816 } 817 818 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> UpdateFieldShortViaAccessor(MemberOffset field_offset,Accessor<int16_t> * accessor)819 inline void Object::UpdateFieldShortViaAccessor(MemberOffset field_offset, 820 Accessor<int16_t>* accessor) { 821 VerifyTransaction<kTransactionActive, kCheckTransaction>(); 822 if (kTransactionActive) { 823 static const bool kIsVolatile = true; 824 int16_t old_value = GetFieldShort<kVerifyFlags, kIsVolatile>(field_offset); 825 Runtime::Current()->RecordWriteFieldShort(this, field_offset, old_value, kIsVolatile); 826 } 827 Verify<kVerifyFlags>(); 828 uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value(); 829 int16_t* addr = reinterpret_cast<int16_t*>(raw_addr); 830 accessor->Access(addr); 831 } 832 833 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> UpdateField32ViaAccessor(MemberOffset field_offset,Accessor<int32_t> * accessor)834 inline void Object::UpdateField32ViaAccessor(MemberOffset field_offset, 835 Accessor<int32_t>* accessor) { 836 VerifyTransaction<kTransactionActive, kCheckTransaction>(); 837 if (kTransactionActive) { 838 static const bool kIsVolatile = true; 839 int32_t old_value = GetField32<kVerifyFlags, kIsVolatile>(field_offset); 840 Runtime::Current()->RecordWriteField32(this, field_offset, old_value, kIsVolatile); 841 } 842 Verify<kVerifyFlags>(); 843 uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value(); 844 int32_t* addr = reinterpret_cast<int32_t*>(raw_addr); 845 accessor->Access(addr); 846 } 847 848 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> UpdateField64ViaAccessor(MemberOffset field_offset,Accessor<int64_t> * accessor)849 inline void Object::UpdateField64ViaAccessor(MemberOffset field_offset, 850 Accessor<int64_t>* accessor) { 851 VerifyTransaction<kTransactionActive, kCheckTransaction>(); 852 if (kTransactionActive) { 853 static const bool kIsVolatile = true; 854 int64_t old_value = GetField64<kVerifyFlags, kIsVolatile>(field_offset); 855 Runtime::Current()->RecordWriteField64(this, field_offset, old_value, kIsVolatile); 856 } 857 Verify<kVerifyFlags>(); 858 uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value(); 859 int64_t* addr = reinterpret_cast<int64_t*>(raw_addr); 860 accessor->Access(addr); 861 } 862 863 template<bool kIsStatic, 864 VerifyObjectFlags kVerifyFlags, 865 ReadBarrierOption kReadBarrierOption, 866 typename Visitor> VisitFieldsReferences(uint32_t ref_offsets,const Visitor & visitor)867 inline void Object::VisitFieldsReferences(uint32_t ref_offsets, const Visitor& visitor) { 868 if (!kIsStatic && (ref_offsets != mirror::Class::kClassWalkSuper)) { 869 // Instance fields and not the slow-path. 870 uint32_t field_offset = mirror::kObjectHeaderSize; 871 while (ref_offsets != 0) { 872 if ((ref_offsets & 1) != 0) { 873 visitor(this, MemberOffset(field_offset), kIsStatic); 874 } 875 ref_offsets >>= 1; 876 field_offset += sizeof(mirror::HeapReference<mirror::Object>); 877 } 878 } else { 879 // There is no reference offset bitmap. In the non-static case, walk up the class 880 // inheritance hierarchy and find reference offsets the hard way. In the static case, just 881 // consider this class. 882 for (ObjPtr<Class> klass = kIsStatic 883 ? ObjPtr<Class>::DownCast(this) 884 : GetClass<kVerifyFlags, kReadBarrierOption>(); 885 klass != nullptr; 886 klass = kIsStatic ? nullptr : klass->GetSuperClass<kVerifyFlags, kReadBarrierOption>()) { 887 const size_t num_reference_fields = 888 kIsStatic ? klass->NumReferenceStaticFields() : klass->NumReferenceInstanceFields(); 889 if (num_reference_fields == 0u) { 890 continue; 891 } 892 // Presumably GC can happen when we are cross compiling, it should not cause performance 893 // problems to do pointer size logic. 894 MemberOffset field_offset = kIsStatic 895 ? klass->GetFirstReferenceStaticFieldOffset<kVerifyFlags>( 896 Runtime::Current()->GetClassLinker()->GetImagePointerSize()) 897 : klass->GetFirstReferenceInstanceFieldOffset<kVerifyFlags, kReadBarrierOption>(); 898 for (size_t i = 0u; i < num_reference_fields; ++i) { 899 // TODO: Do a simpler check? 900 if (field_offset.Uint32Value() != ClassOffset().Uint32Value()) { 901 visitor(this, field_offset, kIsStatic); 902 } 903 field_offset = MemberOffset(field_offset.Uint32Value() + 904 sizeof(mirror::HeapReference<mirror::Object>)); 905 } 906 } 907 } 908 } 909 910 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption, typename Visitor> VisitInstanceFieldsReferences(ObjPtr<Class> klass,const Visitor & visitor)911 inline void Object::VisitInstanceFieldsReferences(ObjPtr<Class> klass, const Visitor& visitor) { 912 VisitFieldsReferences<false, kVerifyFlags, kReadBarrierOption>( 913 klass->GetReferenceInstanceOffsets<kVerifyFlags>(), visitor); 914 } 915 916 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption, typename Visitor> VisitStaticFieldsReferences(ObjPtr<Class> klass,const Visitor & visitor)917 inline void Object::VisitStaticFieldsReferences(ObjPtr<Class> klass, const Visitor& visitor) { 918 DCHECK(!klass->IsTemp<kVerifyFlags>()); 919 klass->VisitFieldsReferences<true, kVerifyFlags, kReadBarrierOption>(0, visitor); 920 } 921 922 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption> IsClassLoader()923 inline bool Object::IsClassLoader() { 924 return GetClass<kVerifyFlags, kReadBarrierOption>()->template IsClassLoaderClass<kVerifyFlags>(); 925 } 926 927 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption> AsClassLoader()928 inline ObjPtr<ClassLoader> Object::AsClassLoader() { 929 DCHECK((IsClassLoader<kVerifyFlags, kReadBarrierOption>())); 930 return ObjPtr<ClassLoader>::DownCast(this); 931 } 932 933 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption> IsDexCache()934 inline bool Object::IsDexCache() { 935 return GetClass<kVerifyFlags, kReadBarrierOption>()->template IsDexCacheClass<kVerifyFlags>(); 936 } 937 938 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption> AsDexCache()939 inline ObjPtr<mirror::DexCache> Object::AsDexCache() { 940 DCHECK((IsDexCache<kVerifyFlags, kReadBarrierOption>())); 941 return ObjPtr<DexCache>::DownCast(this); 942 } 943 944 template<bool kTransactionActive, bool kCheckTransaction> VerifyTransaction()945 inline void Object::VerifyTransaction() { 946 if (kCheckTransaction) { 947 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction()); 948 } 949 } 950 951 } // namespace mirror 952 } // namespace art 953 954 #endif // ART_RUNTIME_MIRROR_OBJECT_INL_H_ 955