1 /* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef ART_RUNTIME_MIRROR_OBJECT_INL_H_ 18 #define ART_RUNTIME_MIRROR_OBJECT_INL_H_ 19 20 #include "object.h" 21 22 #include "art_field.h" 23 #include "art_method.h" 24 #include "atomic.h" 25 #include "array-inl.h" 26 #include "class.h" 27 #include "lock_word-inl.h" 28 #include "monitor.h" 29 #include "object_array-inl.h" 30 #include "read_barrier-inl.h" 31 #include "runtime.h" 32 #include "reference.h" 33 #include "throwable.h" 34 35 namespace art { 36 namespace mirror { 37 ClassSize()38 inline uint32_t Object::ClassSize() { 39 uint32_t vtable_entries = kVTableLength; 40 return Class::ComputeClassSize(true, vtable_entries, 0, 0, 0); 41 } 42 43 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption> GetClass()44 inline Class* Object::GetClass() { 45 return GetFieldObject<Class, kVerifyFlags, kReadBarrierOption>( 46 OFFSET_OF_OBJECT_MEMBER(Object, klass_)); 47 } 48 49 template<VerifyObjectFlags kVerifyFlags> SetClass(Class * new_klass)50 inline void Object::SetClass(Class* new_klass) { 51 // new_klass may be NULL prior to class linker initialization. 52 // We don't mark the card as this occurs as part of object allocation. Not all objects have 53 // backing cards, such as large objects. 54 // We use non transactional version since we can't undo this write. We also disable checking as 55 // we may run in transaction mode here. 56 SetFieldObjectWithoutWriteBarrier<false, false, 57 static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis)>( 58 OFFSET_OF_OBJECT_MEMBER(Object, klass_), new_klass); 59 } 60 GetLockWord(bool as_volatile)61 inline LockWord Object::GetLockWord(bool as_volatile) { 62 if (as_volatile) { 63 return LockWord(GetField32Volatile(OFFSET_OF_OBJECT_MEMBER(Object, monitor_))); 64 } 65 return LockWord(GetField32(OFFSET_OF_OBJECT_MEMBER(Object, monitor_))); 66 } 67 SetLockWord(LockWord new_val,bool as_volatile)68 inline void Object::SetLockWord(LockWord new_val, bool as_volatile) { 69 // Force use of non-transactional mode and do not check. 70 if (as_volatile) { 71 SetField32Volatile<false, false>(OFFSET_OF_OBJECT_MEMBER(Object, monitor_), new_val.GetValue()); 72 } else { 73 SetField32<false, false>(OFFSET_OF_OBJECT_MEMBER(Object, monitor_), new_val.GetValue()); 74 } 75 } 76 CasLockWordWeakSequentiallyConsistent(LockWord old_val,LockWord new_val)77 inline bool Object::CasLockWordWeakSequentiallyConsistent(LockWord old_val, LockWord new_val) { 78 // Force use of non-transactional mode and do not check. 79 return CasFieldWeakSequentiallyConsistent32<false, false>( 80 OFFSET_OF_OBJECT_MEMBER(Object, monitor_), old_val.GetValue(), new_val.GetValue()); 81 } 82 CasLockWordWeakRelaxed(LockWord old_val,LockWord new_val)83 inline bool Object::CasLockWordWeakRelaxed(LockWord old_val, LockWord new_val) { 84 // Force use of non-transactional mode and do not check. 85 return CasFieldWeakRelaxed32<false, false>( 86 OFFSET_OF_OBJECT_MEMBER(Object, monitor_), old_val.GetValue(), new_val.GetValue()); 87 } 88 GetLockOwnerThreadId()89 inline uint32_t Object::GetLockOwnerThreadId() { 90 return Monitor::GetLockOwnerThreadId(this); 91 } 92 MonitorEnter(Thread * self)93 inline mirror::Object* Object::MonitorEnter(Thread* self) { 94 return Monitor::MonitorEnter(self, this); 95 } 96 MonitorExit(Thread * self)97 inline bool Object::MonitorExit(Thread* self) { 98 return Monitor::MonitorExit(self, this); 99 } 100 Notify(Thread * self)101 inline void Object::Notify(Thread* self) { 102 Monitor::Notify(self, this); 103 } 104 NotifyAll(Thread * self)105 inline void Object::NotifyAll(Thread* self) { 106 Monitor::NotifyAll(self, this); 107 } 108 Wait(Thread * self)109 inline void Object::Wait(Thread* self) { 110 Monitor::Wait(self, this, 0, 0, true, kWaiting); 111 } 112 Wait(Thread * self,int64_t ms,int32_t ns)113 inline void Object::Wait(Thread* self, int64_t ms, int32_t ns) { 114 Monitor::Wait(self, this, ms, ns, true, kTimedWaiting); 115 } 116 GetReadBarrierPointer()117 inline Object* Object::GetReadBarrierPointer() { 118 #ifdef USE_BAKER_OR_BROOKS_READ_BARRIER 119 DCHECK(kUseBakerOrBrooksReadBarrier); 120 return GetFieldObject<Object, kVerifyNone, kWithoutReadBarrier>( 121 OFFSET_OF_OBJECT_MEMBER(Object, x_rb_ptr_)); 122 #else 123 LOG(FATAL) << "Unreachable"; 124 return nullptr; 125 #endif 126 } 127 SetReadBarrierPointer(Object * rb_ptr)128 inline void Object::SetReadBarrierPointer(Object* rb_ptr) { 129 #ifdef USE_BAKER_OR_BROOKS_READ_BARRIER 130 DCHECK(kUseBakerOrBrooksReadBarrier); 131 // We don't mark the card as this occurs as part of object allocation. Not all objects have 132 // backing cards, such as large objects. 133 SetFieldObjectWithoutWriteBarrier<false, false, kVerifyNone>( 134 OFFSET_OF_OBJECT_MEMBER(Object, x_rb_ptr_), rb_ptr); 135 #else 136 LOG(FATAL) << "Unreachable"; 137 #endif 138 } 139 AtomicSetReadBarrierPointer(Object * expected_rb_ptr,Object * rb_ptr)140 inline bool Object::AtomicSetReadBarrierPointer(Object* expected_rb_ptr, Object* rb_ptr) { 141 #ifdef USE_BAKER_OR_BROOKS_READ_BARRIER 142 DCHECK(kUseBakerOrBrooksReadBarrier); 143 MemberOffset offset = OFFSET_OF_OBJECT_MEMBER(Object, x_rb_ptr_); 144 byte* raw_addr = reinterpret_cast<byte*>(this) + offset.SizeValue(); 145 Atomic<uint32_t>* atomic_rb_ptr = reinterpret_cast<Atomic<uint32_t>*>(raw_addr); 146 HeapReference<Object> expected_ref(HeapReference<Object>::FromMirrorPtr(expected_rb_ptr)); 147 HeapReference<Object> new_ref(HeapReference<Object>::FromMirrorPtr(rb_ptr)); 148 do { 149 if (UNLIKELY(atomic_rb_ptr->LoadRelaxed() != expected_ref.reference_)) { 150 // Lost the race. 151 return false; 152 } 153 } while (!atomic_rb_ptr->CompareExchangeWeakSequentiallyConsistent(expected_ref.reference_, 154 new_ref.reference_)); 155 DCHECK_EQ(new_ref.reference_, atomic_rb_ptr->LoadRelaxed()); 156 return true; 157 #else 158 LOG(FATAL) << "Unreachable"; 159 return false; 160 #endif 161 } 162 AssertReadBarrierPointer()163 inline void Object::AssertReadBarrierPointer() const { 164 if (kUseBakerReadBarrier) { 165 Object* obj = const_cast<Object*>(this); 166 DCHECK(obj->GetReadBarrierPointer() == nullptr) 167 << "Bad Baker pointer: obj=" << reinterpret_cast<void*>(obj) 168 << " ptr=" << reinterpret_cast<void*>(obj->GetReadBarrierPointer()); 169 } else if (kUseBrooksReadBarrier) { 170 Object* obj = const_cast<Object*>(this); 171 DCHECK_EQ(obj, obj->GetReadBarrierPointer()) 172 << "Bad Brooks pointer: obj=" << reinterpret_cast<void*>(obj) 173 << " ptr=" << reinterpret_cast<void*>(obj->GetReadBarrierPointer()); 174 } else { 175 LOG(FATAL) << "Unreachable"; 176 } 177 } 178 179 template<VerifyObjectFlags kVerifyFlags> VerifierInstanceOf(Class * klass)180 inline bool Object::VerifierInstanceOf(Class* klass) { 181 DCHECK(klass != NULL); 182 DCHECK(GetClass<kVerifyFlags>() != NULL); 183 return klass->IsInterface() || InstanceOf(klass); 184 } 185 186 template<VerifyObjectFlags kVerifyFlags> InstanceOf(Class * klass)187 inline bool Object::InstanceOf(Class* klass) { 188 DCHECK(klass != NULL); 189 DCHECK(GetClass<kVerifyNone>() != NULL); 190 return klass->IsAssignableFrom(GetClass<kVerifyFlags>()); 191 } 192 193 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption> IsClass()194 inline bool Object::IsClass() { 195 Class* java_lang_Class = GetClass<kVerifyFlags, kReadBarrierOption>()-> 196 template GetClass<kVerifyFlags, kReadBarrierOption>(); 197 return GetClass<static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis), 198 kReadBarrierOption>() == java_lang_Class; 199 } 200 201 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption> AsClass()202 inline Class* Object::AsClass() { 203 DCHECK((IsClass<kVerifyFlags, kReadBarrierOption>())); 204 return down_cast<Class*>(this); 205 } 206 207 template<VerifyObjectFlags kVerifyFlags> IsObjectArray()208 inline bool Object::IsObjectArray() { 209 constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis); 210 return IsArrayInstance<kVerifyFlags>() && 211 !GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitive(); 212 } 213 214 template<class T, VerifyObjectFlags kVerifyFlags> AsObjectArray()215 inline ObjectArray<T>* Object::AsObjectArray() { 216 DCHECK(IsObjectArray<kVerifyFlags>()); 217 return down_cast<ObjectArray<T>*>(this); 218 } 219 220 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption> IsArrayInstance()221 inline bool Object::IsArrayInstance() { 222 return GetClass<kVerifyFlags, kReadBarrierOption>()-> 223 template IsArrayClass<kVerifyFlags, kReadBarrierOption>(); 224 } 225 226 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption> IsArtField()227 inline bool Object::IsArtField() { 228 return GetClass<kVerifyFlags, kReadBarrierOption>()-> 229 template IsArtFieldClass<kReadBarrierOption>(); 230 } 231 232 template<VerifyObjectFlags kVerifyFlags> AsArtField()233 inline ArtField* Object::AsArtField() { 234 DCHECK(IsArtField<kVerifyFlags>()); 235 return down_cast<ArtField*>(this); 236 } 237 238 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption> IsArtMethod()239 inline bool Object::IsArtMethod() { 240 return GetClass<kVerifyFlags, kReadBarrierOption>()-> 241 template IsArtMethodClass<kReadBarrierOption>(); 242 } 243 244 template<VerifyObjectFlags kVerifyFlags> AsArtMethod()245 inline ArtMethod* Object::AsArtMethod() { 246 DCHECK(IsArtMethod<kVerifyFlags>()); 247 return down_cast<ArtMethod*>(this); 248 } 249 250 template<VerifyObjectFlags kVerifyFlags> IsReferenceInstance()251 inline bool Object::IsReferenceInstance() { 252 return GetClass<kVerifyFlags>()->IsTypeOfReferenceClass(); 253 } 254 255 template<VerifyObjectFlags kVerifyFlags> AsReference()256 inline Reference* Object::AsReference() { 257 DCHECK(IsReferenceInstance<kVerifyFlags>()); 258 return down_cast<Reference*>(this); 259 } 260 261 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption> AsArray()262 inline Array* Object::AsArray() { 263 DCHECK((IsArrayInstance<kVerifyFlags, kReadBarrierOption>())); 264 return down_cast<Array*>(this); 265 } 266 267 template<VerifyObjectFlags kVerifyFlags> AsBooleanArray()268 inline BooleanArray* Object::AsBooleanArray() { 269 constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis); 270 DCHECK(GetClass<kVerifyFlags>()->IsArrayClass()); 271 DCHECK(GetClass<kNewFlags>()->GetComponentType()->IsPrimitiveBoolean()); 272 return down_cast<BooleanArray*>(this); 273 } 274 275 template<VerifyObjectFlags kVerifyFlags> AsByteArray()276 inline ByteArray* Object::AsByteArray() { 277 static const VerifyObjectFlags kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis); 278 DCHECK(GetClass<kVerifyFlags>()->IsArrayClass()); 279 DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveByte()); 280 return down_cast<ByteArray*>(this); 281 } 282 283 template<VerifyObjectFlags kVerifyFlags> AsByteSizedArray()284 inline ByteArray* Object::AsByteSizedArray() { 285 constexpr VerifyObjectFlags kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis); 286 DCHECK(GetClass<kVerifyFlags>()->IsArrayClass()); 287 DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveByte() || 288 GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveBoolean()); 289 return down_cast<ByteArray*>(this); 290 } 291 292 template<VerifyObjectFlags kVerifyFlags> AsCharArray()293 inline CharArray* Object::AsCharArray() { 294 constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis); 295 DCHECK(GetClass<kVerifyFlags>()->IsArrayClass()); 296 DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveChar()); 297 return down_cast<CharArray*>(this); 298 } 299 300 template<VerifyObjectFlags kVerifyFlags> AsShortArray()301 inline ShortArray* Object::AsShortArray() { 302 constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis); 303 DCHECK(GetClass<kVerifyFlags>()->IsArrayClass()); 304 DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveShort()); 305 return down_cast<ShortArray*>(this); 306 } 307 308 template<VerifyObjectFlags kVerifyFlags> AsShortSizedArray()309 inline ShortArray* Object::AsShortSizedArray() { 310 constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis); 311 DCHECK(GetClass<kVerifyFlags>()->IsArrayClass()); 312 DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveShort() || 313 GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveChar()); 314 return down_cast<ShortArray*>(this); 315 } 316 317 template<VerifyObjectFlags kVerifyFlags> AsIntArray()318 inline IntArray* Object::AsIntArray() { 319 constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis); 320 DCHECK(GetClass<kVerifyFlags>()->IsArrayClass()); 321 DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveInt() || 322 GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveFloat()); 323 return down_cast<IntArray*>(this); 324 } 325 326 template<VerifyObjectFlags kVerifyFlags> AsLongArray()327 inline LongArray* Object::AsLongArray() { 328 constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis); 329 DCHECK(GetClass<kVerifyFlags>()->IsArrayClass()); 330 DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveLong() || 331 GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveDouble()); 332 return down_cast<LongArray*>(this); 333 } 334 335 template<VerifyObjectFlags kVerifyFlags> AsFloatArray()336 inline FloatArray* Object::AsFloatArray() { 337 constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis); 338 DCHECK(GetClass<kVerifyFlags>()->IsArrayClass()); 339 DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveFloat()); 340 return down_cast<FloatArray*>(this); 341 } 342 343 template<VerifyObjectFlags kVerifyFlags> AsDoubleArray()344 inline DoubleArray* Object::AsDoubleArray() { 345 constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis); 346 DCHECK(GetClass<kVerifyFlags>()->IsArrayClass()); 347 DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveDouble()); 348 return down_cast<DoubleArray*>(this); 349 } 350 351 template<VerifyObjectFlags kVerifyFlags> AsString()352 inline String* Object::AsString() { 353 DCHECK(GetClass<kVerifyFlags>()->IsStringClass()); 354 return down_cast<String*>(this); 355 } 356 357 template<VerifyObjectFlags kVerifyFlags> AsThrowable()358 inline Throwable* Object::AsThrowable() { 359 DCHECK(GetClass<kVerifyFlags>()->IsThrowableClass()); 360 return down_cast<Throwable*>(this); 361 } 362 363 template<VerifyObjectFlags kVerifyFlags> IsWeakReferenceInstance()364 inline bool Object::IsWeakReferenceInstance() { 365 return GetClass<kVerifyFlags>()->IsWeakReferenceClass(); 366 } 367 368 template<VerifyObjectFlags kVerifyFlags> IsSoftReferenceInstance()369 inline bool Object::IsSoftReferenceInstance() { 370 return GetClass<kVerifyFlags>()->IsSoftReferenceClass(); 371 } 372 373 template<VerifyObjectFlags kVerifyFlags> IsFinalizerReferenceInstance()374 inline bool Object::IsFinalizerReferenceInstance() { 375 return GetClass<kVerifyFlags>()->IsFinalizerReferenceClass(); 376 } 377 378 template<VerifyObjectFlags kVerifyFlags> AsFinalizerReference()379 inline FinalizerReference* Object::AsFinalizerReference() { 380 DCHECK(IsFinalizerReferenceInstance<kVerifyFlags>()); 381 return down_cast<FinalizerReference*>(this); 382 } 383 384 template<VerifyObjectFlags kVerifyFlags> IsPhantomReferenceInstance()385 inline bool Object::IsPhantomReferenceInstance() { 386 return GetClass<kVerifyFlags>()->IsPhantomReferenceClass(); 387 } 388 389 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption> SizeOf()390 inline size_t Object::SizeOf() { 391 size_t result; 392 constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis); 393 if (IsArrayInstance<kVerifyFlags, kReadBarrierOption>()) { 394 result = AsArray<kNewFlags, kReadBarrierOption>()-> 395 template SizeOf<kNewFlags, kReadBarrierOption>(); 396 } else if (IsClass<kNewFlags, kReadBarrierOption>()) { 397 result = AsClass<kNewFlags, kReadBarrierOption>()-> 398 template SizeOf<kNewFlags, kReadBarrierOption>(); 399 } else { 400 result = GetClass<kNewFlags, kReadBarrierOption>()-> 401 template GetObjectSize<kNewFlags, kReadBarrierOption>(); 402 } 403 DCHECK_GE(result, sizeof(Object)) 404 << " class=" << PrettyTypeOf(GetClass<kNewFlags, kReadBarrierOption>()); 405 DCHECK(!(IsArtField<kNewFlags, kReadBarrierOption>()) || result == sizeof(ArtField)); 406 DCHECK(!(IsArtMethod<kNewFlags, kReadBarrierOption>()) || result == sizeof(ArtMethod)); 407 return result; 408 } 409 410 template<VerifyObjectFlags kVerifyFlags, bool kIsVolatile> GetField32(MemberOffset field_offset)411 inline int32_t Object::GetField32(MemberOffset field_offset) { 412 if (kVerifyFlags & kVerifyThis) { 413 VerifyObject(this); 414 } 415 const byte* raw_addr = reinterpret_cast<const byte*>(this) + field_offset.Int32Value(); 416 const int32_t* word_addr = reinterpret_cast<const int32_t*>(raw_addr); 417 if (UNLIKELY(kIsVolatile)) { 418 return reinterpret_cast<const Atomic<int32_t>*>(word_addr)->LoadSequentiallyConsistent(); 419 } else { 420 return reinterpret_cast<const Atomic<int32_t>*>(word_addr)->LoadJavaData(); 421 } 422 } 423 424 template<VerifyObjectFlags kVerifyFlags> GetField32Volatile(MemberOffset field_offset)425 inline int32_t Object::GetField32Volatile(MemberOffset field_offset) { 426 return GetField32<kVerifyFlags, true>(field_offset); 427 } 428 429 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags, 430 bool kIsVolatile> SetField32(MemberOffset field_offset,int32_t new_value)431 inline void Object::SetField32(MemberOffset field_offset, int32_t new_value) { 432 if (kCheckTransaction) { 433 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction()); 434 } 435 if (kTransactionActive) { 436 Runtime::Current()->RecordWriteField32(this, field_offset, 437 GetField32<kVerifyFlags, kIsVolatile>(field_offset), 438 kIsVolatile); 439 } 440 if (kVerifyFlags & kVerifyThis) { 441 VerifyObject(this); 442 } 443 byte* raw_addr = reinterpret_cast<byte*>(this) + field_offset.Int32Value(); 444 int32_t* word_addr = reinterpret_cast<int32_t*>(raw_addr); 445 if (kIsVolatile) { 446 reinterpret_cast<Atomic<int32_t>*>(word_addr)->StoreSequentiallyConsistent(new_value); 447 } else { 448 reinterpret_cast<Atomic<int32_t>*>(word_addr)->StoreJavaData(new_value); 449 } 450 } 451 452 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> SetField32Volatile(MemberOffset field_offset,int32_t new_value)453 inline void Object::SetField32Volatile(MemberOffset field_offset, int32_t new_value) { 454 SetField32<kTransactionActive, kCheckTransaction, kVerifyFlags, true>(field_offset, new_value); 455 } 456 457 // TODO: Pass memory_order_ and strong/weak as arguments to avoid code duplication? 458 459 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> CasFieldWeakSequentiallyConsistent32(MemberOffset field_offset,int32_t old_value,int32_t new_value)460 inline bool Object::CasFieldWeakSequentiallyConsistent32(MemberOffset field_offset, 461 int32_t old_value, int32_t new_value) { 462 if (kCheckTransaction) { 463 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction()); 464 } 465 if (kTransactionActive) { 466 Runtime::Current()->RecordWriteField32(this, field_offset, old_value, true); 467 } 468 if (kVerifyFlags & kVerifyThis) { 469 VerifyObject(this); 470 } 471 byte* raw_addr = reinterpret_cast<byte*>(this) + field_offset.Int32Value(); 472 AtomicInteger* atomic_addr = reinterpret_cast<AtomicInteger*>(raw_addr); 473 474 return atomic_addr->CompareExchangeWeakSequentiallyConsistent(old_value, new_value); 475 } 476 477 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> CasFieldWeakRelaxed32(MemberOffset field_offset,int32_t old_value,int32_t new_value)478 inline bool Object::CasFieldWeakRelaxed32(MemberOffset field_offset, 479 int32_t old_value, int32_t new_value) { 480 if (kCheckTransaction) { 481 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction()); 482 } 483 if (kTransactionActive) { 484 Runtime::Current()->RecordWriteField32(this, field_offset, old_value, true); 485 } 486 if (kVerifyFlags & kVerifyThis) { 487 VerifyObject(this); 488 } 489 byte* raw_addr = reinterpret_cast<byte*>(this) + field_offset.Int32Value(); 490 AtomicInteger* atomic_addr = reinterpret_cast<AtomicInteger*>(raw_addr); 491 492 return atomic_addr->CompareExchangeWeakRelaxed(old_value, new_value); 493 } 494 495 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> CasFieldStrongSequentiallyConsistent32(MemberOffset field_offset,int32_t old_value,int32_t new_value)496 inline bool Object::CasFieldStrongSequentiallyConsistent32(MemberOffset field_offset, 497 int32_t old_value, int32_t new_value) { 498 if (kCheckTransaction) { 499 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction()); 500 } 501 if (kTransactionActive) { 502 Runtime::Current()->RecordWriteField32(this, field_offset, old_value, true); 503 } 504 if (kVerifyFlags & kVerifyThis) { 505 VerifyObject(this); 506 } 507 byte* raw_addr = reinterpret_cast<byte*>(this) + field_offset.Int32Value(); 508 AtomicInteger* atomic_addr = reinterpret_cast<AtomicInteger*>(raw_addr); 509 510 return atomic_addr->CompareExchangeStrongSequentiallyConsistent(old_value, new_value); 511 } 512 513 template<VerifyObjectFlags kVerifyFlags, bool kIsVolatile> GetField64(MemberOffset field_offset)514 inline int64_t Object::GetField64(MemberOffset field_offset) { 515 if (kVerifyFlags & kVerifyThis) { 516 VerifyObject(this); 517 } 518 const byte* raw_addr = reinterpret_cast<const byte*>(this) + field_offset.Int32Value(); 519 const int64_t* addr = reinterpret_cast<const int64_t*>(raw_addr); 520 if (kIsVolatile) { 521 return reinterpret_cast<const Atomic<int64_t>*>(addr)->LoadSequentiallyConsistent(); 522 } else { 523 return reinterpret_cast<const Atomic<int64_t>*>(addr)->LoadJavaData(); 524 } 525 } 526 527 template<VerifyObjectFlags kVerifyFlags> GetField64Volatile(MemberOffset field_offset)528 inline int64_t Object::GetField64Volatile(MemberOffset field_offset) { 529 return GetField64<kVerifyFlags, true>(field_offset); 530 } 531 532 template<bool kTransactionActive, bool kCheckTransaction, 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 if (kCheckTransaction) { 536 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction()); 537 } 538 if (kTransactionActive) { 539 Runtime::Current()->RecordWriteField64(this, field_offset, 540 GetField64<kVerifyFlags, kIsVolatile>(field_offset), 541 kIsVolatile); 542 } 543 if (kVerifyFlags & kVerifyThis) { 544 VerifyObject(this); 545 } 546 byte* raw_addr = reinterpret_cast<byte*>(this) + field_offset.Int32Value(); 547 int64_t* addr = reinterpret_cast<int64_t*>(raw_addr); 548 if (kIsVolatile) { 549 reinterpret_cast<Atomic<int64_t>*>(addr)->StoreSequentiallyConsistent(new_value); 550 } else { 551 reinterpret_cast<Atomic<int64_t>*>(addr)->StoreJavaData(new_value); 552 } 553 } 554 555 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> SetField64Volatile(MemberOffset field_offset,int64_t new_value)556 inline void Object::SetField64Volatile(MemberOffset field_offset, int64_t new_value) { 557 return SetField64<kTransactionActive, kCheckTransaction, kVerifyFlags, true>(field_offset, 558 new_value); 559 } 560 561 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> CasFieldWeakSequentiallyConsistent64(MemberOffset field_offset,int64_t old_value,int64_t new_value)562 inline bool Object::CasFieldWeakSequentiallyConsistent64(MemberOffset field_offset, 563 int64_t old_value, int64_t new_value) { 564 if (kCheckTransaction) { 565 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction()); 566 } 567 if (kTransactionActive) { 568 Runtime::Current()->RecordWriteField64(this, field_offset, old_value, true); 569 } 570 if (kVerifyFlags & kVerifyThis) { 571 VerifyObject(this); 572 } 573 byte* raw_addr = reinterpret_cast<byte*>(this) + field_offset.Int32Value(); 574 Atomic<int64_t>* atomic_addr = reinterpret_cast<Atomic<int64_t>*>(raw_addr); 575 return atomic_addr->CompareExchangeWeakSequentiallyConsistent(old_value, new_value); 576 } 577 578 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> CasFieldStrongSequentiallyConsistent64(MemberOffset field_offset,int64_t old_value,int64_t new_value)579 inline bool Object::CasFieldStrongSequentiallyConsistent64(MemberOffset field_offset, 580 int64_t old_value, int64_t new_value) { 581 if (kCheckTransaction) { 582 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction()); 583 } 584 if (kTransactionActive) { 585 Runtime::Current()->RecordWriteField64(this, field_offset, old_value, true); 586 } 587 if (kVerifyFlags & kVerifyThis) { 588 VerifyObject(this); 589 } 590 byte* raw_addr = reinterpret_cast<byte*>(this) + field_offset.Int32Value(); 591 Atomic<int64_t>* atomic_addr = reinterpret_cast<Atomic<int64_t>*>(raw_addr); 592 return atomic_addr->CompareExchangeStrongSequentiallyConsistent(old_value, new_value); 593 } 594 595 template<class T, VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption, 596 bool kIsVolatile> GetFieldObject(MemberOffset field_offset)597 inline T* Object::GetFieldObject(MemberOffset field_offset) { 598 if (kVerifyFlags & kVerifyThis) { 599 VerifyObject(this); 600 } 601 byte* raw_addr = reinterpret_cast<byte*>(this) + field_offset.Int32Value(); 602 HeapReference<T>* objref_addr = reinterpret_cast<HeapReference<T>*>(raw_addr); 603 T* result = ReadBarrier::Barrier<T, kReadBarrierOption>(this, field_offset, objref_addr); 604 if (kIsVolatile) { 605 // TODO: Refactor to use a SequentiallyConsistent load instead. 606 QuasiAtomic::ThreadFenceAcquire(); // Ensure visibility of operations preceding store. 607 } 608 if (kVerifyFlags & kVerifyReads) { 609 VerifyObject(result); 610 } 611 return result; 612 } 613 614 template<class T, VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption> GetFieldObjectVolatile(MemberOffset field_offset)615 inline T* Object::GetFieldObjectVolatile(MemberOffset field_offset) { 616 return GetFieldObject<T, kVerifyFlags, kReadBarrierOption, true>(field_offset); 617 } 618 619 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags, 620 bool kIsVolatile> SetFieldObjectWithoutWriteBarrier(MemberOffset field_offset,Object * new_value)621 inline void Object::SetFieldObjectWithoutWriteBarrier(MemberOffset field_offset, 622 Object* new_value) { 623 if (kCheckTransaction) { 624 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction()); 625 } 626 if (kTransactionActive) { 627 mirror::Object* obj; 628 if (kIsVolatile) { 629 obj = GetFieldObjectVolatile<Object>(field_offset); 630 } else { 631 obj = GetFieldObject<Object>(field_offset); 632 } 633 Runtime::Current()->RecordWriteFieldReference(this, field_offset, obj, true); 634 } 635 if (kVerifyFlags & kVerifyThis) { 636 VerifyObject(this); 637 } 638 if (kVerifyFlags & kVerifyWrites) { 639 VerifyObject(new_value); 640 } 641 byte* raw_addr = reinterpret_cast<byte*>(this) + field_offset.Int32Value(); 642 HeapReference<Object>* objref_addr = reinterpret_cast<HeapReference<Object>*>(raw_addr); 643 if (kIsVolatile) { 644 // TODO: Refactor to use a SequentiallyConsistent store instead. 645 QuasiAtomic::ThreadFenceRelease(); // Ensure that prior accesses are visible before store. 646 objref_addr->Assign(new_value); 647 QuasiAtomic::ThreadFenceSequentiallyConsistent(); 648 // Ensure this store occurs before any volatile loads. 649 } else { 650 objref_addr->Assign(new_value); 651 } 652 } 653 654 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags, 655 bool kIsVolatile> SetFieldObject(MemberOffset field_offset,Object * new_value)656 inline void Object::SetFieldObject(MemberOffset field_offset, Object* new_value) { 657 SetFieldObjectWithoutWriteBarrier<kTransactionActive, kCheckTransaction, kVerifyFlags, 658 kIsVolatile>(field_offset, new_value); 659 if (new_value != nullptr) { 660 Runtime::Current()->GetHeap()->WriteBarrierField(this, field_offset, new_value); 661 // TODO: Check field assignment could theoretically cause thread suspension, TODO: fix this. 662 CheckFieldAssignment(field_offset, new_value); 663 } 664 } 665 666 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> SetFieldObjectVolatile(MemberOffset field_offset,Object * new_value)667 inline void Object::SetFieldObjectVolatile(MemberOffset field_offset, Object* new_value) { 668 SetFieldObject<kTransactionActive, kCheckTransaction, kVerifyFlags, true>(field_offset, 669 new_value); 670 } 671 672 template <VerifyObjectFlags kVerifyFlags> GetFieldObjectReferenceAddr(MemberOffset field_offset)673 inline HeapReference<Object>* Object::GetFieldObjectReferenceAddr(MemberOffset field_offset) { 674 if (kVerifyFlags & kVerifyThis) { 675 VerifyObject(this); 676 } 677 return reinterpret_cast<HeapReference<Object>*>(reinterpret_cast<byte*>(this) + 678 field_offset.Int32Value()); 679 } 680 681 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> CasFieldWeakSequentiallyConsistentObject(MemberOffset field_offset,Object * old_value,Object * new_value)682 inline bool Object::CasFieldWeakSequentiallyConsistentObject(MemberOffset field_offset, 683 Object* old_value, Object* new_value) { 684 if (kCheckTransaction) { 685 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction()); 686 } 687 if (kVerifyFlags & kVerifyThis) { 688 VerifyObject(this); 689 } 690 if (kVerifyFlags & kVerifyWrites) { 691 VerifyObject(new_value); 692 } 693 if (kVerifyFlags & kVerifyReads) { 694 VerifyObject(old_value); 695 } 696 if (kTransactionActive) { 697 Runtime::Current()->RecordWriteFieldReference(this, field_offset, old_value, true); 698 } 699 HeapReference<Object> old_ref(HeapReference<Object>::FromMirrorPtr(old_value)); 700 HeapReference<Object> new_ref(HeapReference<Object>::FromMirrorPtr(new_value)); 701 byte* raw_addr = reinterpret_cast<byte*>(this) + field_offset.Int32Value(); 702 Atomic<uint32_t>* atomic_addr = reinterpret_cast<Atomic<uint32_t>*>(raw_addr); 703 704 bool success = atomic_addr->CompareExchangeWeakSequentiallyConsistent(old_ref.reference_, 705 new_ref.reference_); 706 707 if (success) { 708 Runtime::Current()->GetHeap()->WriteBarrierField(this, field_offset, new_value); 709 } 710 return success; 711 } 712 713 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> CasFieldStrongSequentiallyConsistentObject(MemberOffset field_offset,Object * old_value,Object * new_value)714 inline bool Object::CasFieldStrongSequentiallyConsistentObject(MemberOffset field_offset, 715 Object* old_value, Object* new_value) { 716 if (kCheckTransaction) { 717 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction()); 718 } 719 if (kVerifyFlags & kVerifyThis) { 720 VerifyObject(this); 721 } 722 if (kVerifyFlags & kVerifyWrites) { 723 VerifyObject(new_value); 724 } 725 if (kVerifyFlags & kVerifyReads) { 726 VerifyObject(old_value); 727 } 728 if (kTransactionActive) { 729 Runtime::Current()->RecordWriteFieldReference(this, field_offset, old_value, true); 730 } 731 HeapReference<Object> old_ref(HeapReference<Object>::FromMirrorPtr(old_value)); 732 HeapReference<Object> new_ref(HeapReference<Object>::FromMirrorPtr(new_value)); 733 byte* raw_addr = reinterpret_cast<byte*>(this) + field_offset.Int32Value(); 734 Atomic<uint32_t>* atomic_addr = reinterpret_cast<Atomic<uint32_t>*>(raw_addr); 735 736 bool success = atomic_addr->CompareExchangeStrongSequentiallyConsistent(old_ref.reference_, 737 new_ref.reference_); 738 739 if (success) { 740 Runtime::Current()->GetHeap()->WriteBarrierField(this, field_offset, new_value); 741 } 742 return success; 743 } 744 745 template<bool kVisitClass, bool kIsStatic, typename Visitor> VisitFieldsReferences(uint32_t ref_offsets,const Visitor & visitor)746 inline void Object::VisitFieldsReferences(uint32_t ref_offsets, const Visitor& visitor) { 747 if (LIKELY(ref_offsets != CLASS_WALK_SUPER)) { 748 if (!kVisitClass) { 749 // Mask out the class from the reference offsets. 750 ref_offsets ^= kWordHighBitMask; 751 } 752 DCHECK_EQ(ClassOffset().Uint32Value(), 0U); 753 // Found a reference offset bitmap. Visit the specified offsets. 754 while (ref_offsets != 0) { 755 size_t right_shift = CLZ(ref_offsets); 756 MemberOffset field_offset = CLASS_OFFSET_FROM_CLZ(right_shift); 757 visitor(this, field_offset, kIsStatic); 758 ref_offsets &= ~(CLASS_HIGH_BIT >> right_shift); 759 } 760 } else { 761 // There is no reference offset bitmap. In the non-static case, walk up the class 762 // inheritance hierarchy and find reference offsets the hard way. In the static case, just 763 // consider this class. 764 for (mirror::Class* klass = kIsStatic ? AsClass() : GetClass(); klass != nullptr; 765 klass = kIsStatic ? nullptr : klass->GetSuperClass()) { 766 size_t num_reference_fields = 767 kIsStatic ? klass->NumReferenceStaticFields() : klass->NumReferenceInstanceFields(); 768 for (size_t i = 0; i < num_reference_fields; ++i) { 769 mirror::ArtField* field = kIsStatic ? klass->GetStaticField(i) : klass->GetInstanceField(i); 770 MemberOffset field_offset = field->GetOffset(); 771 // TODO: Do a simpler check? 772 if (kVisitClass || field_offset.Uint32Value() != ClassOffset().Uint32Value()) { 773 visitor(this, field_offset, kIsStatic); 774 } 775 } 776 } 777 } 778 } 779 780 template<bool kVisitClass, typename Visitor> VisitInstanceFieldsReferences(mirror::Class * klass,const Visitor & visitor)781 inline void Object::VisitInstanceFieldsReferences(mirror::Class* klass, const Visitor& visitor) { 782 VisitFieldsReferences<kVisitClass, false>( 783 klass->GetReferenceInstanceOffsets<kVerifyNone>(), visitor); 784 } 785 786 template<bool kVisitClass, typename Visitor> VisitStaticFieldsReferences(mirror::Class * klass,const Visitor & visitor)787 inline void Object::VisitStaticFieldsReferences(mirror::Class* klass, const Visitor& visitor) { 788 DCHECK(!klass->IsTemp()); 789 klass->VisitFieldsReferences<kVisitClass, true>( 790 klass->GetReferenceStaticOffsets<kVerifyNone>(), visitor); 791 } 792 793 template <const bool kVisitClass, VerifyObjectFlags kVerifyFlags, typename Visitor, 794 typename JavaLangRefVisitor> VisitReferences(const Visitor & visitor,const JavaLangRefVisitor & ref_visitor)795 inline void Object::VisitReferences(const Visitor& visitor, 796 const JavaLangRefVisitor& ref_visitor) { 797 mirror::Class* klass = GetClass<kVerifyFlags>(); 798 if (klass == Class::GetJavaLangClass()) { 799 AsClass<kVerifyNone>()->VisitReferences<kVisitClass>(klass, visitor); 800 } else if (klass->IsArrayClass()) { 801 if (klass->IsObjectArrayClass<kVerifyNone>()) { 802 AsObjectArray<mirror::Object, kVerifyNone>()->VisitReferences<kVisitClass>(visitor); 803 } else if (kVisitClass) { 804 visitor(this, ClassOffset(), false); 805 } 806 } else { 807 DCHECK(!klass->IsVariableSize()); 808 VisitInstanceFieldsReferences<kVisitClass>(klass, visitor); 809 if (UNLIKELY(klass->IsTypeOfReferenceClass<kVerifyNone>())) { 810 ref_visitor(klass, AsReference()); 811 } 812 } 813 } 814 815 } // namespace mirror 816 } // namespace art 817 818 #endif // ART_RUNTIME_MIRROR_OBJECT_INL_H_ 819