object-inl.h revision 800ac2defde5d12b2f1f313c6b6162560cfa6fc7
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 "read_barrier-inl.h"
30#include "runtime.h"
31#include "reference.h"
32#include "throwable.h"
33
34namespace art {
35namespace mirror {
36
37template<VerifyObjectFlags kVerifyFlags>
38inline Class* Object::GetClass() {
39  return GetFieldObject<Class, kVerifyFlags>(OFFSET_OF_OBJECT_MEMBER(Object, klass_), false);
40}
41
42template<VerifyObjectFlags kVerifyFlags>
43inline void Object::SetClass(Class* new_klass) {
44  // new_klass may be NULL prior to class linker initialization.
45  // We don't mark the card as this occurs as part of object allocation. Not all objects have
46  // backing cards, such as large objects.
47  // We use non transactional version since we can't undo this write. We also disable checking as
48  // we may run in transaction mode here.
49  SetFieldObjectWithoutWriteBarrier<false, false,
50      static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis)>(
51      OFFSET_OF_OBJECT_MEMBER(Object, klass_), new_klass, false);
52}
53
54inline LockWord Object::GetLockWord() {
55  return LockWord(GetField32(OFFSET_OF_OBJECT_MEMBER(Object, monitor_), true));
56}
57
58inline void Object::SetLockWord(LockWord new_val) {
59  // Force use of non-transactional mode and do not check.
60  SetField32<false, false>(OFFSET_OF_OBJECT_MEMBER(Object, monitor_), new_val.GetValue(), true);
61}
62
63inline bool Object::CasLockWord(LockWord old_val, LockWord new_val) {
64  // Force use of non-transactional mode and do not check.
65  return CasField32<false, false>(OFFSET_OF_OBJECT_MEMBER(Object, monitor_), old_val.GetValue(),
66                                  new_val.GetValue());
67}
68
69inline uint32_t Object::GetLockOwnerThreadId() {
70  return Monitor::GetLockOwnerThreadId(this);
71}
72
73inline mirror::Object* Object::MonitorEnter(Thread* self) {
74  return Monitor::MonitorEnter(self, this);
75}
76
77inline bool Object::MonitorExit(Thread* self) {
78  return Monitor::MonitorExit(self, this);
79}
80
81inline void Object::Notify(Thread* self) {
82  Monitor::Notify(self, this);
83}
84
85inline void Object::NotifyAll(Thread* self) {
86  Monitor::NotifyAll(self, this);
87}
88
89inline void Object::Wait(Thread* self) {
90  Monitor::Wait(self, this, 0, 0, true, kWaiting);
91}
92
93inline void Object::Wait(Thread* self, int64_t ms, int32_t ns) {
94  Monitor::Wait(self, this, ms, ns, true, kTimedWaiting);
95}
96
97inline Object* Object::GetReadBarrierPointer() {
98#ifdef USE_BAKER_OR_BROOKS_READ_BARRIER
99  DCHECK(kUseBakerOrBrooksReadBarrier);
100  return GetFieldObject<Object, kVerifyNone, false>(OFFSET_OF_OBJECT_MEMBER(Object, x_rb_ptr_), false);
101#else
102  LOG(FATAL) << "Unreachable";
103  return nullptr;
104#endif
105}
106
107inline void Object::SetReadBarrierPointer(Object* rb_pointer) {
108#ifdef USE_BAKER_OR_BROOKS_READ_BARRIER
109  DCHECK(kUseBakerOrBrooksReadBarrier);
110  // We don't mark the card as this occurs as part of object allocation. Not all objects have
111  // backing cards, such as large objects.
112  SetFieldObjectWithoutWriteBarrier<false, false, kVerifyNone>(
113      OFFSET_OF_OBJECT_MEMBER(Object, x_rb_ptr_), rb_pointer, false);
114#else
115  LOG(FATAL) << "Unreachable";
116#endif
117}
118
119inline void Object::AssertReadBarrierPointer() const {
120  if (kUseBakerReadBarrier) {
121    Object* obj = const_cast<Object*>(this);
122    DCHECK(obj->GetReadBarrierPointer() == nullptr)
123        << "Bad Baker pointer: obj=" << reinterpret_cast<void*>(obj)
124        << " ptr=" << reinterpret_cast<void*>(obj->GetReadBarrierPointer());
125  } else if (kUseBrooksReadBarrier) {
126    Object* obj = const_cast<Object*>(this);
127    DCHECK_EQ(obj, obj->GetReadBarrierPointer())
128        << "Bad Brooks pointer: obj=" << reinterpret_cast<void*>(obj)
129        << " ptr=" << reinterpret_cast<void*>(obj->GetReadBarrierPointer());
130  } else {
131    LOG(FATAL) << "Unreachable";
132  }
133}
134
135template<VerifyObjectFlags kVerifyFlags>
136inline bool Object::VerifierInstanceOf(Class* klass) {
137  DCHECK(klass != NULL);
138  DCHECK(GetClass<kVerifyFlags>() != NULL);
139  return klass->IsInterface() || InstanceOf(klass);
140}
141
142template<VerifyObjectFlags kVerifyFlags>
143inline bool Object::InstanceOf(Class* klass) {
144  DCHECK(klass != NULL);
145  DCHECK(GetClass<kVerifyNone>() != NULL);
146  return klass->IsAssignableFrom(GetClass<kVerifyFlags>());
147}
148
149template<VerifyObjectFlags kVerifyFlags>
150inline bool Object::IsClass() {
151  Class* java_lang_Class = GetClass<kVerifyFlags>()->GetClass();
152  return GetClass<static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis)>() ==
153      java_lang_Class;
154}
155
156template<VerifyObjectFlags kVerifyFlags>
157inline Class* Object::AsClass() {
158  DCHECK(IsClass<kVerifyFlags>());
159  return down_cast<Class*>(this);
160}
161
162template<VerifyObjectFlags kVerifyFlags>
163inline bool Object::IsObjectArray() {
164  constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
165  return IsArrayInstance<kVerifyFlags>() &&
166      !GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitive();
167}
168
169template<class T, VerifyObjectFlags kVerifyFlags>
170inline ObjectArray<T>* Object::AsObjectArray() {
171  DCHECK(IsObjectArray<kVerifyFlags>());
172  return down_cast<ObjectArray<T>*>(this);
173}
174
175template<VerifyObjectFlags kVerifyFlags>
176inline bool Object::IsArrayInstance() {
177  return GetClass<kVerifyFlags>()->IsArrayClass();
178}
179
180template<VerifyObjectFlags kVerifyFlags>
181inline bool Object::IsArtField() {
182  return GetClass<kVerifyFlags>()->IsArtFieldClass();
183}
184
185template<VerifyObjectFlags kVerifyFlags>
186inline ArtField* Object::AsArtField() {
187  DCHECK(IsArtField<kVerifyFlags>());
188  return down_cast<ArtField*>(this);
189}
190
191template<VerifyObjectFlags kVerifyFlags>
192inline bool Object::IsArtMethod() {
193  return GetClass<kVerifyFlags>()->IsArtMethodClass();
194}
195
196template<VerifyObjectFlags kVerifyFlags>
197inline ArtMethod* Object::AsArtMethod() {
198  DCHECK(IsArtMethod<kVerifyFlags>());
199  return down_cast<ArtMethod*>(this);
200}
201
202template<VerifyObjectFlags kVerifyFlags>
203inline bool Object::IsReferenceInstance() {
204  return GetClass<kVerifyFlags>()->IsReferenceClass();
205}
206
207template<VerifyObjectFlags kVerifyFlags>
208inline Reference* Object::AsReference() {
209  DCHECK(IsReferenceInstance<kVerifyFlags>());
210  return down_cast<Reference*>(this);
211}
212
213template<VerifyObjectFlags kVerifyFlags>
214inline Array* Object::AsArray() {
215  DCHECK(IsArrayInstance<kVerifyFlags>());
216  return down_cast<Array*>(this);
217}
218
219template<VerifyObjectFlags kVerifyFlags>
220inline BooleanArray* Object::AsBooleanArray() {
221  constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
222  DCHECK(GetClass<kVerifyFlags>()->IsArrayClass());
223  DCHECK(GetClass<kNewFlags>()->GetComponentType()->IsPrimitiveBoolean());
224  return down_cast<BooleanArray*>(this);
225}
226
227template<VerifyObjectFlags kVerifyFlags>
228inline ByteArray* Object::AsByteArray() {
229  static const VerifyObjectFlags kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
230  DCHECK(GetClass<kVerifyFlags>()->IsArrayClass());
231  DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveByte());
232  return down_cast<ByteArray*>(this);
233}
234
235template<VerifyObjectFlags kVerifyFlags>
236inline ByteArray* Object::AsByteSizedArray() {
237  constexpr VerifyObjectFlags kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
238  DCHECK(GetClass<kVerifyFlags>()->IsArrayClass());
239  DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveByte() ||
240         GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveBoolean());
241  return down_cast<ByteArray*>(this);
242}
243
244template<VerifyObjectFlags kVerifyFlags>
245inline CharArray* Object::AsCharArray() {
246  constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
247  DCHECK(GetClass<kVerifyFlags>()->IsArrayClass());
248  DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveChar());
249  return down_cast<CharArray*>(this);
250}
251
252template<VerifyObjectFlags kVerifyFlags>
253inline ShortArray* Object::AsShortArray() {
254  constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
255  DCHECK(GetClass<kVerifyFlags>()->IsArrayClass());
256  DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveShort());
257  return down_cast<ShortArray*>(this);
258}
259
260template<VerifyObjectFlags kVerifyFlags>
261inline ShortArray* Object::AsShortSizedArray() {
262  constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
263  DCHECK(GetClass<kVerifyFlags>()->IsArrayClass());
264  DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveShort() ||
265         GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveChar());
266  return down_cast<ShortArray*>(this);
267}
268
269template<VerifyObjectFlags kVerifyFlags>
270inline IntArray* Object::AsIntArray() {
271  constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
272  DCHECK(GetClass<kVerifyFlags>()->IsArrayClass());
273  DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveInt() ||
274         GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveFloat());
275  return down_cast<IntArray*>(this);
276}
277
278template<VerifyObjectFlags kVerifyFlags>
279inline LongArray* Object::AsLongArray() {
280  constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
281  DCHECK(GetClass<kVerifyFlags>()->IsArrayClass());
282  DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveLong() ||
283         GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveDouble());
284  return down_cast<LongArray*>(this);
285}
286
287template<VerifyObjectFlags kVerifyFlags>
288inline FloatArray* Object::AsFloatArray() {
289  constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
290  DCHECK(GetClass<kVerifyFlags>()->IsArrayClass());
291  DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveFloat());
292  return down_cast<FloatArray*>(this);
293}
294
295template<VerifyObjectFlags kVerifyFlags>
296inline DoubleArray* Object::AsDoubleArray() {
297  constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
298  DCHECK(GetClass<kVerifyFlags>()->IsArrayClass());
299  DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveDouble());
300  return down_cast<DoubleArray*>(this);
301}
302
303template<VerifyObjectFlags kVerifyFlags>
304inline String* Object::AsString() {
305  DCHECK(GetClass<kVerifyFlags>()->IsStringClass());
306  return down_cast<String*>(this);
307}
308
309template<VerifyObjectFlags kVerifyFlags>
310inline Throwable* Object::AsThrowable() {
311  DCHECK(GetClass<kVerifyFlags>()->IsThrowableClass());
312  return down_cast<Throwable*>(this);
313}
314
315template<VerifyObjectFlags kVerifyFlags>
316inline bool Object::IsWeakReferenceInstance() {
317  return GetClass<kVerifyFlags>()->IsWeakReferenceClass();
318}
319
320template<VerifyObjectFlags kVerifyFlags>
321inline bool Object::IsSoftReferenceInstance() {
322  return GetClass<kVerifyFlags>()->IsSoftReferenceClass();
323}
324
325template<VerifyObjectFlags kVerifyFlags>
326inline bool Object::IsFinalizerReferenceInstance() {
327  return GetClass<kVerifyFlags>()->IsFinalizerReferenceClass();
328}
329
330template<VerifyObjectFlags kVerifyFlags>
331inline FinalizerReference* Object::AsFinalizerReference() {
332  DCHECK(IsFinalizerReferenceInstance<kVerifyFlags>());
333  return down_cast<FinalizerReference*>(this);
334}
335
336template<VerifyObjectFlags kVerifyFlags>
337inline bool Object::IsPhantomReferenceInstance() {
338  return GetClass<kVerifyFlags>()->IsPhantomReferenceClass();
339}
340
341template<VerifyObjectFlags kVerifyFlags>
342inline size_t Object::SizeOf() {
343  size_t result;
344  constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
345  if (IsArrayInstance<kVerifyFlags>()) {
346    result = AsArray<kNewFlags>()->template SizeOf<kNewFlags>();
347  } else if (IsClass<kNewFlags>()) {
348    result = AsClass<kNewFlags>()->template SizeOf<kNewFlags>();
349  } else {
350    result = GetClass<kNewFlags>()->GetObjectSize();
351  }
352  DCHECK_GE(result, sizeof(Object)) << " class=" << PrettyTypeOf(GetClass<kNewFlags>());
353  DCHECK(!IsArtField<kNewFlags>()  || result == sizeof(ArtField));
354  DCHECK(!IsArtMethod<kNewFlags>() || result == sizeof(ArtMethod));
355  return result;
356}
357
358template<VerifyObjectFlags kVerifyFlags>
359inline int32_t Object::GetField32(MemberOffset field_offset, bool is_volatile) {
360  if (kVerifyFlags & kVerifyThis) {
361    VerifyObject(this);
362  }
363  const byte* raw_addr = reinterpret_cast<const byte*>(this) + field_offset.Int32Value();
364  const int32_t* word_addr = reinterpret_cast<const int32_t*>(raw_addr);
365  if (UNLIKELY(is_volatile)) {
366    int32_t result = *(reinterpret_cast<volatile int32_t*>(const_cast<int32_t*>(word_addr)));
367    QuasiAtomic::MembarLoadLoad();  // Ensure volatile loads don't re-order.
368    return result;
369  } else {
370    return *word_addr;
371  }
372}
373
374template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
375inline void Object::SetField32(MemberOffset field_offset, int32_t new_value, bool is_volatile) {
376  if (kCheckTransaction) {
377    DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
378  }
379  if (kTransactionActive) {
380    Runtime::Current()->RecordWriteField32(this, field_offset, GetField32(field_offset, is_volatile),
381                                           is_volatile);
382  }
383  if (kVerifyFlags & kVerifyThis) {
384    VerifyObject(this);
385  }
386  byte* raw_addr = reinterpret_cast<byte*>(this) + field_offset.Int32Value();
387  int32_t* word_addr = reinterpret_cast<int32_t*>(raw_addr);
388  if (UNLIKELY(is_volatile)) {
389    QuasiAtomic::MembarStoreStore();  // Ensure this store occurs after others in the queue.
390    *word_addr = new_value;
391    QuasiAtomic::MembarStoreLoad();  // Ensure this store occurs before any volatile loads.
392  } else {
393    *word_addr = new_value;
394  }
395}
396
397template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
398inline bool Object::CasField32(MemberOffset field_offset, int32_t old_value, int32_t new_value) {
399  if (kCheckTransaction) {
400    DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
401  }
402  if (kTransactionActive) {
403    Runtime::Current()->RecordWriteField32(this, field_offset, old_value, true);
404  }
405  if (kVerifyFlags & kVerifyThis) {
406    VerifyObject(this);
407  }
408  byte* raw_addr = reinterpret_cast<byte*>(this) + field_offset.Int32Value();
409  volatile int32_t* addr = reinterpret_cast<volatile int32_t*>(raw_addr);
410  return __sync_bool_compare_and_swap(addr, old_value, new_value);
411}
412
413template<VerifyObjectFlags kVerifyFlags>
414inline int64_t Object::GetField64(MemberOffset field_offset, bool is_volatile) {
415  if (kVerifyFlags & kVerifyThis) {
416    VerifyObject(this);
417  }
418  const byte* raw_addr = reinterpret_cast<const byte*>(this) + field_offset.Int32Value();
419  const int64_t* addr = reinterpret_cast<const int64_t*>(raw_addr);
420  if (UNLIKELY(is_volatile)) {
421    int64_t result = QuasiAtomic::Read64(addr);
422    QuasiAtomic::MembarLoadLoad();  // Ensure volatile loads don't re-order.
423    return result;
424  } else {
425    return *addr;
426  }
427}
428
429template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
430inline void Object::SetField64(MemberOffset field_offset, int64_t new_value, bool is_volatile) {
431  if (kCheckTransaction) {
432    DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
433  }
434  if (kTransactionActive) {
435    Runtime::Current()->RecordWriteField64(this, field_offset, GetField64(field_offset, is_volatile),
436                                           is_volatile);
437  }
438  if (kVerifyFlags & kVerifyThis) {
439    VerifyObject(this);
440  }
441  byte* raw_addr = reinterpret_cast<byte*>(this) + field_offset.Int32Value();
442  int64_t* addr = reinterpret_cast<int64_t*>(raw_addr);
443  if (UNLIKELY(is_volatile)) {
444    QuasiAtomic::MembarStoreStore();  // Ensure this store occurs after others in the queue.
445    QuasiAtomic::Write64(addr, new_value);
446    if (!QuasiAtomic::LongAtomicsUseMutexes()) {
447      QuasiAtomic::MembarStoreLoad();  // Ensure this store occurs before any volatile loads.
448    } else {
449      // Fence from from mutex is enough.
450    }
451  } else {
452    *addr = new_value;
453  }
454}
455
456template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
457inline bool Object::CasField64(MemberOffset field_offset, int64_t old_value, int64_t new_value) {
458  if (kCheckTransaction) {
459    DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
460  }
461  if (kTransactionActive) {
462    Runtime::Current()->RecordWriteField64(this, field_offset, old_value, true);
463  }
464  if (kVerifyFlags & kVerifyThis) {
465    VerifyObject(this);
466  }
467  byte* raw_addr = reinterpret_cast<byte*>(this) + field_offset.Int32Value();
468  volatile int64_t* addr = reinterpret_cast<volatile int64_t*>(raw_addr);
469  return QuasiAtomic::Cas64(old_value, new_value, addr);
470}
471
472template<class T, VerifyObjectFlags kVerifyFlags, bool kDoReadBarrier>
473inline T* Object::GetFieldObject(MemberOffset field_offset, bool is_volatile) {
474  if (kVerifyFlags & kVerifyThis) {
475    VerifyObject(this);
476  }
477  byte* raw_addr = reinterpret_cast<byte*>(this) + field_offset.Int32Value();
478  HeapReference<T>* objref_addr = reinterpret_cast<HeapReference<T>*>(raw_addr);
479  T* result = ReadBarrier::Barrier<T, kDoReadBarrier>(this, field_offset, objref_addr);
480  if (UNLIKELY(is_volatile)) {
481    QuasiAtomic::MembarLoadLoad();  // Ensure loads don't re-order.
482  }
483  if (kVerifyFlags & kVerifyReads) {
484    VerifyObject(result);
485  }
486  return result;
487}
488
489template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
490inline void Object::SetFieldObjectWithoutWriteBarrier(MemberOffset field_offset, Object* new_value,
491                                                      bool is_volatile) {
492  if (kCheckTransaction) {
493    DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
494  }
495  if (kTransactionActive) {
496    Runtime::Current()->RecordWriteFieldReference(this, field_offset,
497                                                  GetFieldObject<Object>(field_offset, is_volatile),
498                                                  true);
499  }
500  if (kVerifyFlags & kVerifyThis) {
501    VerifyObject(this);
502  }
503  if (kVerifyFlags & kVerifyWrites) {
504    VerifyObject(new_value);
505  }
506  byte* raw_addr = reinterpret_cast<byte*>(this) + field_offset.Int32Value();
507  HeapReference<Object>* objref_addr = reinterpret_cast<HeapReference<Object>*>(raw_addr);
508  if (UNLIKELY(is_volatile)) {
509    QuasiAtomic::MembarStoreStore();  // Ensure this store occurs after others in the queue.
510    objref_addr->Assign(new_value);
511    QuasiAtomic::MembarStoreLoad();  // Ensure this store occurs before any loads.
512  } else {
513    objref_addr->Assign(new_value);
514  }
515}
516
517template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
518inline void Object::SetFieldObject(MemberOffset field_offset, Object* new_value, bool is_volatile) {
519  SetFieldObjectWithoutWriteBarrier<kTransactionActive, kCheckTransaction, kVerifyFlags>(
520      field_offset, new_value, is_volatile);
521  if (new_value != nullptr) {
522    CheckFieldAssignment(field_offset, new_value);
523    Runtime::Current()->GetHeap()->WriteBarrierField(this, field_offset, new_value);
524  }
525}
526
527template <VerifyObjectFlags kVerifyFlags>
528inline HeapReference<Object>* Object::GetFieldObjectReferenceAddr(MemberOffset field_offset) {
529  if (kVerifyFlags & kVerifyThis) {
530    VerifyObject(this);
531  }
532  return reinterpret_cast<HeapReference<Object>*>(reinterpret_cast<byte*>(this) +
533      field_offset.Int32Value());
534}
535
536template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
537inline bool Object::CasFieldObject(MemberOffset field_offset, Object* old_value,
538                                   Object* new_value) {
539  if (kCheckTransaction) {
540    DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
541  }
542  if (kVerifyFlags & kVerifyThis) {
543    VerifyObject(this);
544  }
545  if (kVerifyFlags & kVerifyWrites) {
546    VerifyObject(new_value);
547  }
548  if (kVerifyFlags & kVerifyReads) {
549    VerifyObject(old_value);
550  }
551  if (kTransactionActive) {
552    Runtime::Current()->RecordWriteFieldReference(this, field_offset, old_value, true);
553  }
554  byte* raw_addr = reinterpret_cast<byte*>(this) + field_offset.Int32Value();
555  volatile int32_t* addr = reinterpret_cast<volatile int32_t*>(raw_addr);
556  HeapReference<Object> old_ref(HeapReference<Object>::FromMirrorPtr(old_value));
557  HeapReference<Object> new_ref(HeapReference<Object>::FromMirrorPtr(new_value));
558  bool success =  __sync_bool_compare_and_swap(addr, old_ref.reference_, new_ref.reference_);
559  if (success) {
560    Runtime::Current()->GetHeap()->WriteBarrierField(this, field_offset, new_value);
561  }
562  return success;
563}
564
565template<bool kVisitClass, bool kIsStatic, typename Visitor>
566inline void Object::VisitFieldsReferences(uint32_t ref_offsets, const Visitor& visitor) {
567  if (LIKELY(ref_offsets != CLASS_WALK_SUPER)) {
568    if (!kVisitClass) {
569     // Mask out the class from the reference offsets.
570      ref_offsets ^= kWordHighBitMask;
571    }
572    DCHECK_EQ(ClassOffset().Uint32Value(), 0U);
573    // Found a reference offset bitmap. Visit the specified offsets.
574    while (ref_offsets != 0) {
575      size_t right_shift = CLZ(ref_offsets);
576      MemberOffset field_offset = CLASS_OFFSET_FROM_CLZ(right_shift);
577      visitor(this, field_offset, kIsStatic);
578      ref_offsets &= ~(CLASS_HIGH_BIT >> right_shift);
579    }
580  } else {
581    // There is no reference offset bitmap.  In the non-static case, walk up the class
582    // inheritance hierarchy and find reference offsets the hard way. In the static case, just
583    // consider this class.
584    for (mirror::Class* klass = kIsStatic ? AsClass() : GetClass(); klass != nullptr;
585        klass = kIsStatic ? nullptr : klass->GetSuperClass()) {
586      size_t num_reference_fields =
587          kIsStatic ? klass->NumReferenceStaticFields() : klass->NumReferenceInstanceFields();
588      for (size_t i = 0; i < num_reference_fields; ++i) {
589        mirror::ArtField* field = kIsStatic ? klass->GetStaticField(i)
590            : klass->GetInstanceField(i);
591        MemberOffset field_offset = field->GetOffset();
592        // TODO: Do a simpler check?
593        if (!kVisitClass && UNLIKELY(field_offset.Uint32Value() == ClassOffset().Uint32Value())) {
594          continue;
595        }
596        visitor(this, field_offset, kIsStatic);
597      }
598    }
599  }
600}
601
602template<bool kVisitClass, typename Visitor>
603inline void Object::VisitInstanceFieldsReferences(mirror::Class* klass, const Visitor& visitor) {
604  VisitFieldsReferences<kVisitClass, false>(
605      klass->GetReferenceInstanceOffsets<kVerifyNone>(), visitor);
606}
607
608template<bool kVisitClass, typename Visitor>
609inline void Object::VisitStaticFieldsReferences(mirror::Class* klass, const Visitor& visitor) {
610  klass->VisitFieldsReferences<kVisitClass, true>(
611      klass->GetReferenceStaticOffsets<kVerifyNone>(), visitor);
612}
613
614template <const bool kVisitClass, VerifyObjectFlags kVerifyFlags, typename Visitor,
615    typename JavaLangRefVisitor>
616inline void Object::VisitReferences(const Visitor& visitor,
617                                    const JavaLangRefVisitor& ref_visitor) {
618  mirror::Class* klass = GetClass<kVerifyFlags>();
619  if (UNLIKELY(klass == Class::GetJavaLangClass())) {
620    DCHECK_EQ(klass->GetClass<kVerifyNone>(), Class::GetJavaLangClass());
621    AsClass<kVerifyNone>()->VisitReferences<kVisitClass>(klass, visitor);
622  } else if (UNLIKELY(klass->IsArrayClass<kVerifyFlags>())) {
623    if (klass->IsObjectArrayClass<kVerifyNone>()) {
624      AsObjectArray<mirror::Object, kVerifyNone>()->VisitReferences<kVisitClass>(visitor);
625    } else if (kVisitClass) {
626      visitor(this, ClassOffset(), false);
627    }
628  } else {
629    VisitInstanceFieldsReferences<kVisitClass>(klass, visitor);
630    if (UNLIKELY(klass->IsReferenceClass<kVerifyNone>())) {
631      ref_visitor(klass, AsReference());
632    }
633  }
634}
635
636}  // namespace mirror
637}  // namespace art
638
639#endif  // ART_RUNTIME_MIRROR_OBJECT_INL_H_
640