object-inl.h revision 4e30541a92381fb280cd0be9a1763b713ee4d64c
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 "runtime.h" 30#include "throwable.h" 31 32namespace art { 33namespace mirror { 34 35template<VerifyObjectFlags kVerifyFlags> 36inline Class* Object::GetClass() { 37 return GetFieldObject<Class, kVerifyFlags>(OFFSET_OF_OBJECT_MEMBER(Object, klass_), false); 38} 39 40template<VerifyObjectFlags kVerifyFlags> 41inline void Object::SetClass(Class* new_klass) { 42 // new_klass may be NULL prior to class linker initialization. 43 // We don't mark the card as this occurs as part of object allocation. Not all objects have 44 // backing cards, such as large objects. 45 // We use non transactional version since we can't undo this write. We also disable checking as 46 // we may run in transaction mode here. 47 SetFieldObjectWithoutWriteBarrier<false, false, 48 static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis)>( 49 OFFSET_OF_OBJECT_MEMBER(Object, klass_), new_klass, false); 50} 51 52inline LockWord Object::GetLockWord() { 53 return LockWord(GetField32(OFFSET_OF_OBJECT_MEMBER(Object, monitor_), true)); 54} 55 56inline void Object::SetLockWord(LockWord new_val) { 57 // Force use of non-transactional mode and do not check. 58 SetField32<false, false>(OFFSET_OF_OBJECT_MEMBER(Object, monitor_), new_val.GetValue(), true); 59} 60 61inline bool Object::CasLockWord(LockWord old_val, LockWord new_val) { 62 // Force use of non-transactional mode and do not check. 63 return CasField32<false, false>(OFFSET_OF_OBJECT_MEMBER(Object, monitor_), old_val.GetValue(), 64 new_val.GetValue()); 65} 66 67inline uint32_t Object::GetLockOwnerThreadId() { 68 return Monitor::GetLockOwnerThreadId(this); 69} 70 71inline mirror::Object* Object::MonitorEnter(Thread* self) { 72 return Monitor::MonitorEnter(self, this); 73} 74 75inline bool Object::MonitorExit(Thread* self) { 76 return Monitor::MonitorExit(self, this); 77} 78 79inline void Object::Notify(Thread* self) { 80 Monitor::Notify(self, this); 81} 82 83inline void Object::NotifyAll(Thread* self) { 84 Monitor::NotifyAll(self, this); 85} 86 87inline void Object::Wait(Thread* self) { 88 Monitor::Wait(self, this, 0, 0, true, kWaiting); 89} 90 91inline void Object::Wait(Thread* self, int64_t ms, int32_t ns) { 92 Monitor::Wait(self, this, ms, ns, true, kTimedWaiting); 93} 94 95template<VerifyObjectFlags kVerifyFlags> 96inline bool Object::VerifierInstanceOf(Class* klass) { 97 DCHECK(klass != NULL); 98 DCHECK(GetClass<kVerifyFlags>() != NULL); 99 return klass->IsInterface() || InstanceOf(klass); 100} 101 102template<VerifyObjectFlags kVerifyFlags> 103inline bool Object::InstanceOf(Class* klass) { 104 DCHECK(klass != NULL); 105 DCHECK(GetClass<kVerifyNone>() != NULL); 106 return klass->IsAssignableFrom(GetClass<kVerifyFlags>()); 107} 108 109template<VerifyObjectFlags kVerifyFlags> 110inline bool Object::IsClass() { 111 Class* java_lang_Class = GetClass<kVerifyFlags>()->GetClass(); 112 return GetClass<static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis)>() == 113 java_lang_Class; 114} 115 116template<VerifyObjectFlags kVerifyFlags> 117inline Class* Object::AsClass() { 118 DCHECK(IsClass<kVerifyFlags>()); 119 return down_cast<Class*>(this); 120} 121 122template<VerifyObjectFlags kVerifyFlags> 123inline bool Object::IsObjectArray() { 124 constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis); 125 return IsArrayInstance<kVerifyFlags>() && 126 !GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitive(); 127} 128 129template<class T, VerifyObjectFlags kVerifyFlags> 130inline ObjectArray<T>* Object::AsObjectArray() { 131 DCHECK(IsObjectArray<kVerifyFlags>()); 132 return down_cast<ObjectArray<T>*>(this); 133} 134 135template<VerifyObjectFlags kVerifyFlags> 136inline bool Object::IsArrayInstance() { 137 return GetClass<kVerifyFlags>()->IsArrayClass(); 138} 139 140template<VerifyObjectFlags kVerifyFlags> 141inline bool Object::IsArtField() { 142 return GetClass<kVerifyFlags>()->IsArtFieldClass(); 143} 144 145template<VerifyObjectFlags kVerifyFlags> 146inline ArtField* Object::AsArtField() { 147 DCHECK(IsArtField<kVerifyFlags>()); 148 return down_cast<ArtField*>(this); 149} 150 151template<VerifyObjectFlags kVerifyFlags> 152inline bool Object::IsArtMethod() { 153 return GetClass<kVerifyFlags>()->IsArtMethodClass(); 154} 155 156template<VerifyObjectFlags kVerifyFlags> 157inline ArtMethod* Object::AsArtMethod() { 158 DCHECK(IsArtMethod<kVerifyFlags>()); 159 return down_cast<ArtMethod*>(this); 160} 161 162template<VerifyObjectFlags kVerifyFlags> 163inline bool Object::IsReferenceInstance() { 164 return GetClass<kVerifyFlags>()->IsReferenceClass(); 165} 166 167template<VerifyObjectFlags kVerifyFlags> 168inline Array* Object::AsArray() { 169 DCHECK(IsArrayInstance<kVerifyFlags>()); 170 return down_cast<Array*>(this); 171} 172 173template<VerifyObjectFlags kVerifyFlags> 174inline BooleanArray* Object::AsBooleanArray() { 175 constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis); 176 DCHECK(GetClass<kVerifyFlags>()->IsArrayClass()); 177 DCHECK(GetClass<kNewFlags>()->GetComponentType()->IsPrimitiveBoolean()); 178 return down_cast<BooleanArray*>(this); 179} 180 181template<VerifyObjectFlags kVerifyFlags> 182inline ByteArray* Object::AsByteArray() { 183 static const VerifyObjectFlags kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis); 184 DCHECK(GetClass<kVerifyFlags>()->IsArrayClass()); 185 DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveByte()); 186 return down_cast<ByteArray*>(this); 187} 188 189template<VerifyObjectFlags kVerifyFlags> 190inline ByteArray* Object::AsByteSizedArray() { 191 constexpr VerifyObjectFlags kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis); 192 DCHECK(GetClass<kVerifyFlags>()->IsArrayClass()); 193 DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveByte() || 194 GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveBoolean()); 195 return down_cast<ByteArray*>(this); 196} 197 198template<VerifyObjectFlags kVerifyFlags> 199inline CharArray* Object::AsCharArray() { 200 constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis); 201 DCHECK(GetClass<kVerifyFlags>()->IsArrayClass()); 202 DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveChar()); 203 return down_cast<CharArray*>(this); 204} 205 206template<VerifyObjectFlags kVerifyFlags> 207inline ShortArray* Object::AsShortArray() { 208 constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis); 209 DCHECK(GetClass<kVerifyFlags>()->IsArrayClass()); 210 DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveShort()); 211 return down_cast<ShortArray*>(this); 212} 213 214template<VerifyObjectFlags kVerifyFlags> 215inline ShortArray* Object::AsShortSizedArray() { 216 constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis); 217 DCHECK(GetClass<kVerifyFlags>()->IsArrayClass()); 218 DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveShort() || 219 GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveChar()); 220 return down_cast<ShortArray*>(this); 221} 222 223template<VerifyObjectFlags kVerifyFlags> 224inline IntArray* Object::AsIntArray() { 225 constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis); 226 DCHECK(GetClass<kVerifyFlags>()->IsArrayClass()); 227 DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveInt() || 228 GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveFloat()); 229 return down_cast<IntArray*>(this); 230} 231 232template<VerifyObjectFlags kVerifyFlags> 233inline LongArray* Object::AsLongArray() { 234 constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis); 235 DCHECK(GetClass<kVerifyFlags>()->IsArrayClass()); 236 DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveLong() || 237 GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveDouble()); 238 return down_cast<LongArray*>(this); 239} 240 241template<VerifyObjectFlags kVerifyFlags> 242inline FloatArray* Object::AsFloatArray() { 243 constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis); 244 DCHECK(GetClass<kVerifyFlags>()->IsArrayClass()); 245 DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveFloat()); 246 return down_cast<FloatArray*>(this); 247} 248 249template<VerifyObjectFlags kVerifyFlags> 250inline DoubleArray* Object::AsDoubleArray() { 251 constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis); 252 DCHECK(GetClass<kVerifyFlags>()->IsArrayClass()); 253 DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveDouble()); 254 return down_cast<DoubleArray*>(this); 255} 256 257template<VerifyObjectFlags kVerifyFlags> 258inline String* Object::AsString() { 259 DCHECK(GetClass<kVerifyFlags>()->IsStringClass()); 260 return down_cast<String*>(this); 261} 262 263template<VerifyObjectFlags kVerifyFlags> 264inline Throwable* Object::AsThrowable() { 265 DCHECK(GetClass<kVerifyFlags>()->IsThrowableClass()); 266 return down_cast<Throwable*>(this); 267} 268 269template<VerifyObjectFlags kVerifyFlags> 270inline bool Object::IsWeakReferenceInstance() { 271 return GetClass<kVerifyFlags>()->IsWeakReferenceClass(); 272} 273 274template<VerifyObjectFlags kVerifyFlags> 275inline bool Object::IsSoftReferenceInstance() { 276 return GetClass<kVerifyFlags>()->IsSoftReferenceClass(); 277} 278 279template<VerifyObjectFlags kVerifyFlags> 280inline bool Object::IsFinalizerReferenceInstance() { 281 return GetClass<kVerifyFlags>()->IsFinalizerReferenceClass(); 282} 283 284template<VerifyObjectFlags kVerifyFlags> 285inline bool Object::IsPhantomReferenceInstance() { 286 return GetClass<kVerifyFlags>()->IsPhantomReferenceClass(); 287} 288 289template<VerifyObjectFlags kVerifyFlags> 290inline size_t Object::SizeOf() { 291 size_t result; 292 constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis); 293 if (IsArrayInstance<kVerifyFlags>()) { 294 result = AsArray<kNewFlags>()->SizeOf<>(); 295 } else if (IsClass<kNewFlags>()) { 296 result = AsClass<kNewFlags>()->SizeOf<kNewFlags>(); 297 } else { 298 result = GetClass<kNewFlags>()->GetObjectSize(); 299 } 300 DCHECK_GE(result, sizeof(Object)) << " class=" << PrettyTypeOf(GetClass<kNewFlags>()); 301 DCHECK(!IsArtField<kNewFlags>() || result == sizeof(ArtField)); 302 DCHECK(!IsArtMethod<kNewFlags>() || result == sizeof(ArtMethod)); 303 return result; 304} 305 306template<VerifyObjectFlags kVerifyFlags> 307inline int32_t Object::GetField32(MemberOffset field_offset, bool is_volatile) { 308 if (kVerifyFlags & kVerifyThis) { 309 VerifyObject(this); 310 } 311 const byte* raw_addr = reinterpret_cast<const byte*>(this) + field_offset.Int32Value(); 312 const int32_t* word_addr = reinterpret_cast<const int32_t*>(raw_addr); 313 if (UNLIKELY(is_volatile)) { 314 int32_t result = *(reinterpret_cast<volatile int32_t*>(const_cast<int32_t*>(word_addr))); 315 QuasiAtomic::MembarLoadLoad(); // Ensure volatile loads don't re-order. 316 return result; 317 } else { 318 return *word_addr; 319 } 320} 321 322template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> 323inline void Object::SetField32(MemberOffset field_offset, int32_t new_value, bool is_volatile) { 324 if (kCheckTransaction) { 325 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction()); 326 } 327 if (kTransactionActive) { 328 Runtime::Current()->RecordWriteField32(this, field_offset, GetField32(field_offset, is_volatile), 329 is_volatile); 330 } 331 if (kVerifyFlags & kVerifyThis) { 332 VerifyObject(this); 333 } 334 byte* raw_addr = reinterpret_cast<byte*>(this) + field_offset.Int32Value(); 335 int32_t* word_addr = reinterpret_cast<int32_t*>(raw_addr); 336 if (UNLIKELY(is_volatile)) { 337 QuasiAtomic::MembarStoreStore(); // Ensure this store occurs after others in the queue. 338 *word_addr = new_value; 339 QuasiAtomic::MembarStoreLoad(); // Ensure this store occurs before any volatile loads. 340 } else { 341 *word_addr = new_value; 342 } 343} 344 345template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> 346inline bool Object::CasField32(MemberOffset field_offset, int32_t old_value, int32_t new_value) { 347 if (kCheckTransaction) { 348 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction()); 349 } 350 if (kTransactionActive) { 351 Runtime::Current()->RecordWriteField32(this, field_offset, old_value, true); 352 } 353 if (kVerifyFlags & kVerifyThis) { 354 VerifyObject(this); 355 } 356 byte* raw_addr = reinterpret_cast<byte*>(this) + field_offset.Int32Value(); 357 volatile int32_t* addr = reinterpret_cast<volatile int32_t*>(raw_addr); 358 return __sync_bool_compare_and_swap(addr, old_value, new_value); 359} 360 361template<VerifyObjectFlags kVerifyFlags> 362inline int64_t Object::GetField64(MemberOffset field_offset, bool is_volatile) { 363 if (kVerifyFlags & kVerifyThis) { 364 VerifyObject(this); 365 } 366 const byte* raw_addr = reinterpret_cast<const byte*>(this) + field_offset.Int32Value(); 367 const int64_t* addr = reinterpret_cast<const int64_t*>(raw_addr); 368 if (UNLIKELY(is_volatile)) { 369 int64_t result = QuasiAtomic::Read64(addr); 370 QuasiAtomic::MembarLoadLoad(); // Ensure volatile loads don't re-order. 371 return result; 372 } else { 373 return *addr; 374 } 375} 376 377template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> 378inline void Object::SetField64(MemberOffset field_offset, int64_t new_value, bool is_volatile) { 379 if (kCheckTransaction) { 380 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction()); 381 } 382 if (kTransactionActive) { 383 Runtime::Current()->RecordWriteField64(this, field_offset, GetField64(field_offset, is_volatile), 384 is_volatile); 385 } 386 if (kVerifyFlags & kVerifyThis) { 387 VerifyObject(this); 388 } 389 byte* raw_addr = reinterpret_cast<byte*>(this) + field_offset.Int32Value(); 390 int64_t* addr = reinterpret_cast<int64_t*>(raw_addr); 391 if (UNLIKELY(is_volatile)) { 392 QuasiAtomic::MembarStoreStore(); // Ensure this store occurs after others in the queue. 393 QuasiAtomic::Write64(addr, new_value); 394 if (!QuasiAtomic::LongAtomicsUseMutexes()) { 395 QuasiAtomic::MembarStoreLoad(); // Ensure this store occurs before any volatile loads. 396 } else { 397 // Fence from from mutex is enough. 398 } 399 } else { 400 *addr = new_value; 401 } 402} 403 404template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> 405inline bool Object::CasField64(MemberOffset field_offset, int64_t old_value, int64_t new_value) { 406 if (kCheckTransaction) { 407 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction()); 408 } 409 if (kTransactionActive) { 410 Runtime::Current()->RecordWriteField64(this, field_offset, old_value, true); 411 } 412 if (kVerifyFlags & kVerifyThis) { 413 VerifyObject(this); 414 } 415 byte* raw_addr = reinterpret_cast<byte*>(this) + field_offset.Int32Value(); 416 volatile int64_t* addr = reinterpret_cast<volatile int64_t*>(raw_addr); 417 return QuasiAtomic::Cas64(old_value, new_value, addr); 418} 419 420template<class T, VerifyObjectFlags kVerifyFlags> 421inline T* Object::GetFieldObject(MemberOffset field_offset, bool is_volatile) { 422 if (kVerifyFlags & kVerifyThis) { 423 VerifyObject(this); 424 } 425 byte* raw_addr = reinterpret_cast<byte*>(this) + field_offset.Int32Value(); 426 HeapReference<T>* objref_addr = reinterpret_cast<HeapReference<T>*>(raw_addr); 427 HeapReference<T> objref = *objref_addr; 428 429 if (UNLIKELY(is_volatile)) { 430 QuasiAtomic::MembarLoadLoad(); // Ensure loads don't re-order. 431 } 432 T* result = objref.AsMirrorPtr(); 433 if (kVerifyFlags & kVerifyReads) { 434 VerifyObject(result); 435 } 436 return result; 437} 438 439template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> 440inline void Object::SetFieldObjectWithoutWriteBarrier(MemberOffset field_offset, Object* new_value, 441 bool is_volatile) { 442 if (kCheckTransaction) { 443 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction()); 444 } 445 if (kTransactionActive) { 446 Runtime::Current()->RecordWriteFieldReference(this, field_offset, 447 GetFieldObject<Object>(field_offset, is_volatile), 448 true); 449 } 450 if (kVerifyFlags & kVerifyThis) { 451 VerifyObject(this); 452 } 453 if (kVerifyFlags & kVerifyWrites) { 454 VerifyObject(new_value); 455 } 456 HeapReference<Object> objref(HeapReference<Object>::FromMirrorPtr(new_value)); 457 byte* raw_addr = reinterpret_cast<byte*>(this) + field_offset.Int32Value(); 458 HeapReference<Object>* objref_addr = reinterpret_cast<HeapReference<Object>*>(raw_addr); 459 if (UNLIKELY(is_volatile)) { 460 QuasiAtomic::MembarStoreStore(); // Ensure this store occurs after others in the queue. 461 objref_addr->Assign(new_value); 462 QuasiAtomic::MembarStoreLoad(); // Ensure this store occurs before any loads. 463 } else { 464 objref_addr->Assign(new_value); 465 } 466} 467 468template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> 469inline void Object::SetFieldObject(MemberOffset field_offset, Object* new_value, bool is_volatile) { 470 SetFieldObjectWithoutWriteBarrier<kTransactionActive, kCheckTransaction, kVerifyFlags>( 471 field_offset, new_value, is_volatile); 472 if (new_value != nullptr) { 473 CheckFieldAssignment(field_offset, new_value); 474 Runtime::Current()->GetHeap()->WriteBarrierField(this, field_offset, new_value); 475 } 476} 477 478template <VerifyObjectFlags kVerifyFlags> 479inline HeapReference<Object>* Object::GetFieldObjectReferenceAddr(MemberOffset field_offset) { 480 if (kVerifyFlags & kVerifyThis) { 481 VerifyObject(this); 482 } 483 return reinterpret_cast<HeapReference<Object>*>(reinterpret_cast<byte*>(this) + 484 field_offset.Int32Value()); 485} 486 487template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags> 488inline bool Object::CasFieldObject(MemberOffset field_offset, Object* old_value, 489 Object* new_value) { 490 if (kCheckTransaction) { 491 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction()); 492 } 493 if (kVerifyFlags & kVerifyThis) { 494 VerifyObject(this); 495 } 496 if (kVerifyFlags & kVerifyWrites) { 497 VerifyObject(new_value); 498 } 499 if (kVerifyFlags & kVerifyReads) { 500 VerifyObject(old_value); 501 } 502 if (kTransactionActive) { 503 Runtime::Current()->RecordWriteFieldReference(this, field_offset, old_value, true); 504 } 505 byte* raw_addr = reinterpret_cast<byte*>(this) + field_offset.Int32Value(); 506 volatile int32_t* addr = reinterpret_cast<volatile int32_t*>(raw_addr); 507 HeapReference<Object> old_ref(HeapReference<Object>::FromMirrorPtr(old_value)); 508 HeapReference<Object> new_ref(HeapReference<Object>::FromMirrorPtr(new_value)); 509 bool success = __sync_bool_compare_and_swap(addr, old_ref.reference_, new_ref.reference_); 510 if (success) { 511 Runtime::Current()->GetHeap()->WriteBarrierField(this, field_offset, new_value); 512 } 513 return success; 514} 515 516} // namespace mirror 517} // namespace art 518 519#endif // ART_RUNTIME_MIRROR_OBJECT_INL_H_ 520