object-inl.h revision 3b45ef277e4a5f7e0314d5df7ef82e480156ba75
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 "reference.h"
32#include "runtime.h"
33#include "string-inl.h"
34#include "throwable.h"
35
36namespace art {
37namespace mirror {
38
39inline uint32_t Object::ClassSize() {
40  uint32_t vtable_entries = kVTableLength;
41  return Class::ComputeClassSize(true, vtable_entries, 0, 0, 0, 0, 0);
42}
43
44template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
45inline Class* Object::GetClass() {
46  return GetFieldObject<Class, kVerifyFlags, kReadBarrierOption>(
47      OFFSET_OF_OBJECT_MEMBER(Object, klass_));
48}
49
50template<VerifyObjectFlags kVerifyFlags>
51inline void Object::SetClass(Class* new_klass) {
52  // new_klass may be null prior to class linker initialization.
53  // We don't mark the card as this occurs as part of object allocation. Not all objects have
54  // backing cards, such as large objects.
55  // We use non transactional version since we can't undo this write. We also disable checking as
56  // we may run in transaction mode here.
57  SetFieldObjectWithoutWriteBarrier<false, false,
58      static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis)>(
59      OFFSET_OF_OBJECT_MEMBER(Object, klass_), new_klass);
60}
61
62template<VerifyObjectFlags kVerifyFlags>
63inline LockWord Object::GetLockWord(bool as_volatile) {
64  if (as_volatile) {
65    return LockWord(GetField32Volatile<kVerifyFlags>(OFFSET_OF_OBJECT_MEMBER(Object, monitor_)));
66  }
67  return LockWord(GetField32<kVerifyFlags>(OFFSET_OF_OBJECT_MEMBER(Object, monitor_)));
68}
69
70template<VerifyObjectFlags kVerifyFlags>
71inline void Object::SetLockWord(LockWord new_val, bool as_volatile) {
72  // Force use of non-transactional mode and do not check.
73  if (as_volatile) {
74    SetField32Volatile<false, false, kVerifyFlags>(
75        OFFSET_OF_OBJECT_MEMBER(Object, monitor_), new_val.GetValue());
76  } else {
77    SetField32<false, false, kVerifyFlags>(
78        OFFSET_OF_OBJECT_MEMBER(Object, monitor_), new_val.GetValue());
79  }
80}
81
82inline bool Object::CasLockWordWeakSequentiallyConsistent(LockWord old_val, LockWord new_val) {
83  // Force use of non-transactional mode and do not check.
84  return CasFieldWeakSequentiallyConsistent32<false, false>(
85      OFFSET_OF_OBJECT_MEMBER(Object, monitor_), old_val.GetValue(), new_val.GetValue());
86}
87
88inline bool Object::CasLockWordWeakRelaxed(LockWord old_val, LockWord new_val) {
89  // Force use of non-transactional mode and do not check.
90  return CasFieldWeakRelaxed32<false, false>(
91      OFFSET_OF_OBJECT_MEMBER(Object, monitor_), old_val.GetValue(), new_val.GetValue());
92}
93
94inline uint32_t Object::GetLockOwnerThreadId() {
95  return Monitor::GetLockOwnerThreadId(this);
96}
97
98inline mirror::Object* Object::MonitorEnter(Thread* self) {
99  return Monitor::MonitorEnter(self, this);
100}
101
102inline bool Object::MonitorExit(Thread* self) {
103  return Monitor::MonitorExit(self, this);
104}
105
106inline void Object::Notify(Thread* self) {
107  Monitor::Notify(self, this);
108}
109
110inline void Object::NotifyAll(Thread* self) {
111  Monitor::NotifyAll(self, this);
112}
113
114inline void Object::Wait(Thread* self) {
115  Monitor::Wait(self, this, 0, 0, true, kWaiting);
116}
117
118inline void Object::Wait(Thread* self, int64_t ms, int32_t ns) {
119  Monitor::Wait(self, this, ms, ns, true, kTimedWaiting);
120}
121
122inline Object* Object::GetReadBarrierPointer() {
123#ifdef USE_BAKER_READ_BARRIER
124  DCHECK(kUseBakerReadBarrier);
125  return reinterpret_cast<Object*>(GetLockWord(false).ReadBarrierState());
126#elif USE_BROOKS_READ_BARRIER
127  DCHECK(kUseBrooksReadBarrier);
128  return GetFieldObject<Object, kVerifyNone, kWithoutReadBarrier>(
129      OFFSET_OF_OBJECT_MEMBER(Object, x_rb_ptr_));
130#else
131  LOG(FATAL) << "Unreachable";
132  UNREACHABLE();
133#endif
134}
135
136inline void Object::SetReadBarrierPointer(Object* rb_ptr) {
137#ifdef USE_BAKER_READ_BARRIER
138  DCHECK(kUseBakerReadBarrier);
139  DCHECK_EQ(reinterpret_cast<uint64_t>(rb_ptr) >> 32, 0U);
140  LockWord lw = GetLockWord(false);
141  lw.SetReadBarrierState(static_cast<uint32_t>(reinterpret_cast<uintptr_t>(rb_ptr)));
142  SetLockWord(lw, false);
143#elif USE_BROOKS_READ_BARRIER
144  DCHECK(kUseBrooksReadBarrier);
145  // We don't mark the card as this occurs as part of object allocation. Not all objects have
146  // backing cards, such as large objects.
147  SetFieldObjectWithoutWriteBarrier<false, false, kVerifyNone>(
148      OFFSET_OF_OBJECT_MEMBER(Object, x_rb_ptr_), rb_ptr);
149#else
150  LOG(FATAL) << "Unreachable";
151  UNREACHABLE();
152  UNUSED(rb_ptr);
153#endif
154}
155
156inline bool Object::AtomicSetReadBarrierPointer(Object* expected_rb_ptr, Object* rb_ptr) {
157#ifdef USE_BAKER_READ_BARRIER
158  DCHECK(kUseBakerReadBarrier);
159  DCHECK_EQ(reinterpret_cast<uint64_t>(expected_rb_ptr) >> 32, 0U);
160  DCHECK_EQ(reinterpret_cast<uint64_t>(rb_ptr) >> 32, 0U);
161  LockWord expected_lw;
162  LockWord new_lw;
163  do {
164    LockWord lw = GetLockWord(false);
165    if (UNLIKELY(reinterpret_cast<Object*>(lw.ReadBarrierState()) != expected_rb_ptr)) {
166      // Lost the race.
167      return false;
168    }
169    expected_lw = lw;
170    expected_lw.SetReadBarrierState(
171        static_cast<uint32_t>(reinterpret_cast<uintptr_t>(expected_rb_ptr)));
172    new_lw = lw;
173    new_lw.SetReadBarrierState(static_cast<uint32_t>(reinterpret_cast<uintptr_t>(rb_ptr)));
174  } while (!CasLockWordWeakSequentiallyConsistent(expected_lw, new_lw));
175  return true;
176#elif USE_BROOKS_READ_BARRIER
177  DCHECK(kUseBrooksReadBarrier);
178  MemberOffset offset = OFFSET_OF_OBJECT_MEMBER(Object, x_rb_ptr_);
179  uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + offset.SizeValue();
180  Atomic<uint32_t>* atomic_rb_ptr = reinterpret_cast<Atomic<uint32_t>*>(raw_addr);
181  HeapReference<Object> expected_ref(HeapReference<Object>::FromMirrorPtr(expected_rb_ptr));
182  HeapReference<Object> new_ref(HeapReference<Object>::FromMirrorPtr(rb_ptr));
183  do {
184    if (UNLIKELY(atomic_rb_ptr->LoadRelaxed() != expected_ref.reference_)) {
185      // Lost the race.
186      return false;
187    }
188  } while (!atomic_rb_ptr->CompareExchangeWeakSequentiallyConsistent(expected_ref.reference_,
189                                                                     new_ref.reference_));
190  return true;
191#else
192  UNUSED(expected_rb_ptr, rb_ptr);
193  LOG(FATAL) << "Unreachable";
194  UNREACHABLE();
195#endif
196}
197
198inline void Object::AssertReadBarrierPointer() const {
199  if (kUseBakerReadBarrier) {
200    Object* obj = const_cast<Object*>(this);
201    DCHECK(obj->GetReadBarrierPointer() == nullptr)
202        << "Bad Baker pointer: obj=" << reinterpret_cast<void*>(obj)
203        << " ptr=" << reinterpret_cast<void*>(obj->GetReadBarrierPointer());
204  } else {
205    CHECK(kUseBrooksReadBarrier);
206    Object* obj = const_cast<Object*>(this);
207    DCHECK_EQ(obj, obj->GetReadBarrierPointer())
208        << "Bad Brooks pointer: obj=" << reinterpret_cast<void*>(obj)
209        << " ptr=" << reinterpret_cast<void*>(obj->GetReadBarrierPointer());
210  }
211}
212
213template<VerifyObjectFlags kVerifyFlags>
214inline bool Object::VerifierInstanceOf(Class* klass) {
215  DCHECK(klass != nullptr);
216  DCHECK(GetClass<kVerifyFlags>() != nullptr);
217  return klass->IsInterface() || InstanceOf(klass);
218}
219
220template<VerifyObjectFlags kVerifyFlags>
221inline bool Object::InstanceOf(Class* klass) {
222  DCHECK(klass != nullptr);
223  DCHECK(GetClass<kVerifyNone>() != nullptr);
224  return klass->IsAssignableFrom(GetClass<kVerifyFlags>());
225}
226
227template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
228inline bool Object::IsClass() {
229  Class* java_lang_Class = GetClass<kVerifyFlags, kReadBarrierOption>()->
230      template GetClass<kVerifyFlags, kReadBarrierOption>();
231  return GetClass<static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis),
232      kReadBarrierOption>() == java_lang_Class;
233}
234
235template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
236inline Class* Object::AsClass() {
237  DCHECK((IsClass<kVerifyFlags, kReadBarrierOption>()));
238  return down_cast<Class*>(this);
239}
240
241template<VerifyObjectFlags kVerifyFlags>
242inline bool Object::IsObjectArray() {
243  constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
244  return IsArrayInstance<kVerifyFlags>() &&
245      !GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitive();
246}
247
248template<class T, VerifyObjectFlags kVerifyFlags>
249inline ObjectArray<T>* Object::AsObjectArray() {
250  DCHECK(IsObjectArray<kVerifyFlags>());
251  return down_cast<ObjectArray<T>*>(this);
252}
253
254template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
255inline bool Object::IsArrayInstance() {
256  return GetClass<kVerifyFlags, kReadBarrierOption>()->
257      template IsArrayClass<kVerifyFlags, kReadBarrierOption>();
258}
259
260template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
261inline bool Object::IsArtMethod() {
262  return GetClass<kVerifyFlags, kReadBarrierOption>()->
263      template IsArtMethodClass<kReadBarrierOption>();
264}
265
266template<VerifyObjectFlags kVerifyFlags>
267inline ArtMethod* Object::AsArtMethod() {
268  DCHECK(IsArtMethod<kVerifyFlags>());
269  return down_cast<ArtMethod*>(this);
270}
271
272template<VerifyObjectFlags kVerifyFlags>
273inline bool Object::IsReferenceInstance() {
274  return GetClass<kVerifyFlags>()->IsTypeOfReferenceClass();
275}
276
277template<VerifyObjectFlags kVerifyFlags>
278inline Reference* Object::AsReference() {
279  DCHECK(IsReferenceInstance<kVerifyFlags>());
280  return down_cast<Reference*>(this);
281}
282
283template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
284inline Array* Object::AsArray() {
285  DCHECK((IsArrayInstance<kVerifyFlags, kReadBarrierOption>()));
286  return down_cast<Array*>(this);
287}
288
289template<VerifyObjectFlags kVerifyFlags>
290inline BooleanArray* Object::AsBooleanArray() {
291  constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
292  DCHECK(GetClass<kVerifyFlags>()->IsArrayClass());
293  DCHECK(GetClass<kNewFlags>()->GetComponentType()->IsPrimitiveBoolean());
294  return down_cast<BooleanArray*>(this);
295}
296
297template<VerifyObjectFlags kVerifyFlags>
298inline ByteArray* Object::AsByteArray() {
299  static const VerifyObjectFlags kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
300  DCHECK(GetClass<kVerifyFlags>()->IsArrayClass());
301  DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveByte());
302  return down_cast<ByteArray*>(this);
303}
304
305template<VerifyObjectFlags kVerifyFlags>
306inline ByteArray* Object::AsByteSizedArray() {
307  constexpr VerifyObjectFlags kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
308  DCHECK(GetClass<kVerifyFlags>()->IsArrayClass());
309  DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveByte() ||
310         GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveBoolean());
311  return down_cast<ByteArray*>(this);
312}
313
314template<VerifyObjectFlags kVerifyFlags>
315inline CharArray* Object::AsCharArray() {
316  constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
317  DCHECK(GetClass<kVerifyFlags>()->IsArrayClass());
318  DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveChar());
319  return down_cast<CharArray*>(this);
320}
321
322template<VerifyObjectFlags kVerifyFlags>
323inline ShortArray* Object::AsShortArray() {
324  constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
325  DCHECK(GetClass<kVerifyFlags>()->IsArrayClass());
326  DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveShort());
327  return down_cast<ShortArray*>(this);
328}
329
330template<VerifyObjectFlags kVerifyFlags>
331inline ShortArray* Object::AsShortSizedArray() {
332  constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
333  DCHECK(GetClass<kVerifyFlags>()->IsArrayClass());
334  DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveShort() ||
335         GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveChar());
336  return down_cast<ShortArray*>(this);
337}
338
339template<VerifyObjectFlags kVerifyFlags>
340inline IntArray* Object::AsIntArray() {
341  constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
342  CHECK(GetClass<kVerifyFlags>()->IsArrayClass());
343  CHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveInt() ||
344         GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveFloat());
345  return down_cast<IntArray*>(this);
346}
347
348template<VerifyObjectFlags kVerifyFlags>
349inline LongArray* Object::AsLongArray() {
350  constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
351  CHECK(GetClass<kVerifyFlags>()->IsArrayClass());
352  CHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveLong() ||
353         GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveDouble());
354  return down_cast<LongArray*>(this);
355}
356
357template<VerifyObjectFlags kVerifyFlags>
358inline FloatArray* Object::AsFloatArray() {
359  constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
360  DCHECK(GetClass<kVerifyFlags>()->IsArrayClass());
361  DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveFloat());
362  return down_cast<FloatArray*>(this);
363}
364
365template<VerifyObjectFlags kVerifyFlags>
366inline DoubleArray* Object::AsDoubleArray() {
367  constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
368  DCHECK(GetClass<kVerifyFlags>()->IsArrayClass());
369  DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveDouble());
370  return down_cast<DoubleArray*>(this);
371}
372
373template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
374inline bool Object::IsString() {
375  return GetClass<kVerifyFlags, kReadBarrierOption>()->IsStringClass();
376}
377
378template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
379inline String* Object::AsString() {
380  DCHECK((IsString<kVerifyFlags, kReadBarrierOption>()));
381  return down_cast<String*>(this);
382}
383
384template<VerifyObjectFlags kVerifyFlags>
385inline Throwable* Object::AsThrowable() {
386  DCHECK(GetClass<kVerifyFlags>()->IsThrowableClass());
387  return down_cast<Throwable*>(this);
388}
389
390template<VerifyObjectFlags kVerifyFlags>
391inline bool Object::IsWeakReferenceInstance() {
392  return GetClass<kVerifyFlags>()->IsWeakReferenceClass();
393}
394
395template<VerifyObjectFlags kVerifyFlags>
396inline bool Object::IsSoftReferenceInstance() {
397  return GetClass<kVerifyFlags>()->IsSoftReferenceClass();
398}
399
400template<VerifyObjectFlags kVerifyFlags>
401inline bool Object::IsFinalizerReferenceInstance() {
402  return GetClass<kVerifyFlags>()->IsFinalizerReferenceClass();
403}
404
405template<VerifyObjectFlags kVerifyFlags>
406inline FinalizerReference* Object::AsFinalizerReference() {
407  DCHECK(IsFinalizerReferenceInstance<kVerifyFlags>());
408  return down_cast<FinalizerReference*>(this);
409}
410
411template<VerifyObjectFlags kVerifyFlags>
412inline bool Object::IsPhantomReferenceInstance() {
413  return GetClass<kVerifyFlags>()->IsPhantomReferenceClass();
414}
415
416template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
417inline size_t Object::SizeOf() {
418  size_t result;
419  constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
420  if (IsArrayInstance<kVerifyFlags, kReadBarrierOption>()) {
421    result = AsArray<kNewFlags, kReadBarrierOption>()->
422        template SizeOf<kNewFlags, kReadBarrierOption>();
423  } else if (IsClass<kNewFlags, kReadBarrierOption>()) {
424    result = AsClass<kNewFlags, kReadBarrierOption>()->
425        template SizeOf<kNewFlags, kReadBarrierOption>();
426  } else if (GetClass<kNewFlags, kReadBarrierOption>()->IsStringClass()) {
427    result = AsString<kNewFlags, kReadBarrierOption>()->
428        template SizeOf<kNewFlags>();
429  } else {
430    result = GetClass<kNewFlags, kReadBarrierOption>()->
431        template GetObjectSize<kNewFlags, kReadBarrierOption>();
432  }
433  DCHECK_GE(result, sizeof(Object))
434      << " class=" << PrettyTypeOf(GetClass<kNewFlags, kReadBarrierOption>());
435  return result;
436}
437
438template<VerifyObjectFlags kVerifyFlags, bool kIsVolatile>
439inline uint8_t Object::GetFieldBoolean(MemberOffset field_offset) {
440  if (kVerifyFlags & kVerifyThis) {
441    VerifyObject(this);
442  }
443  return GetField<uint8_t, kIsVolatile>(field_offset);
444}
445
446template<VerifyObjectFlags kVerifyFlags, bool kIsVolatile>
447inline int8_t Object::GetFieldByte(MemberOffset field_offset) {
448  if (kVerifyFlags & kVerifyThis) {
449    VerifyObject(this);
450  }
451  return GetField<int8_t, kIsVolatile>(field_offset);
452}
453
454template<VerifyObjectFlags kVerifyFlags>
455inline uint8_t Object::GetFieldBooleanVolatile(MemberOffset field_offset) {
456  return GetFieldBoolean<kVerifyFlags, true>(field_offset);
457}
458
459template<VerifyObjectFlags kVerifyFlags>
460inline int8_t Object::GetFieldByteVolatile(MemberOffset field_offset) {
461  return GetFieldByte<kVerifyFlags, true>(field_offset);
462}
463
464template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags,
465    bool kIsVolatile>
466inline void Object::SetFieldBoolean(MemberOffset field_offset, uint8_t new_value)
467    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
468  if (kCheckTransaction) {
469    DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
470  }
471  if (kTransactionActive) {
472    Runtime::Current()->RecordWriteFieldBoolean(this, field_offset,
473                                           GetFieldBoolean<kVerifyFlags, kIsVolatile>(field_offset),
474                                           kIsVolatile);
475  }
476  if (kVerifyFlags & kVerifyThis) {
477    VerifyObject(this);
478  }
479  SetField<uint8_t, kIsVolatile>(field_offset, new_value);
480}
481
482template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags,
483    bool kIsVolatile>
484inline void Object::SetFieldByte(MemberOffset field_offset, int8_t new_value)
485    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
486  if (kCheckTransaction) {
487    DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
488  }
489  if (kTransactionActive) {
490    Runtime::Current()->RecordWriteFieldByte(this, field_offset,
491                                           GetFieldByte<kVerifyFlags, kIsVolatile>(field_offset),
492                                           kIsVolatile);
493  }
494  if (kVerifyFlags & kVerifyThis) {
495    VerifyObject(this);
496  }
497  SetField<int8_t, kIsVolatile>(field_offset, new_value);
498}
499
500template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
501inline void Object::SetFieldBooleanVolatile(MemberOffset field_offset, uint8_t new_value) {
502  return SetFieldBoolean<kTransactionActive, kCheckTransaction, kVerifyFlags, true>(
503      field_offset, new_value);
504}
505
506template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
507inline void Object::SetFieldByteVolatile(MemberOffset field_offset, int8_t new_value) {
508  return SetFieldByte<kTransactionActive, kCheckTransaction, kVerifyFlags, true>(
509      field_offset, new_value);
510}
511
512template<VerifyObjectFlags kVerifyFlags, bool kIsVolatile>
513inline uint16_t Object::GetFieldChar(MemberOffset field_offset) {
514  if (kVerifyFlags & kVerifyThis) {
515    VerifyObject(this);
516  }
517  return GetField<uint16_t, kIsVolatile>(field_offset);
518}
519
520template<VerifyObjectFlags kVerifyFlags, bool kIsVolatile>
521inline int16_t Object::GetFieldShort(MemberOffset field_offset) {
522  if (kVerifyFlags & kVerifyThis) {
523    VerifyObject(this);
524  }
525  return GetField<int16_t, kIsVolatile>(field_offset);
526}
527
528template<VerifyObjectFlags kVerifyFlags>
529inline uint16_t Object::GetFieldCharVolatile(MemberOffset field_offset) {
530  return GetFieldChar<kVerifyFlags, true>(field_offset);
531}
532
533template<VerifyObjectFlags kVerifyFlags>
534inline int16_t Object::GetFieldShortVolatile(MemberOffset field_offset) {
535  return GetFieldShort<kVerifyFlags, true>(field_offset);
536}
537
538template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags,
539    bool kIsVolatile>
540inline void Object::SetFieldChar(MemberOffset field_offset, uint16_t new_value) {
541  if (kCheckTransaction) {
542    DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
543  }
544  if (kTransactionActive) {
545    Runtime::Current()->RecordWriteFieldChar(this, field_offset,
546                                           GetFieldChar<kVerifyFlags, kIsVolatile>(field_offset),
547                                           kIsVolatile);
548  }
549  if (kVerifyFlags & kVerifyThis) {
550    VerifyObject(this);
551  }
552  SetField<uint16_t, kIsVolatile>(field_offset, new_value);
553}
554
555template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags,
556    bool kIsVolatile>
557inline void Object::SetFieldShort(MemberOffset field_offset, int16_t new_value) {
558  if (kCheckTransaction) {
559    DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
560  }
561  if (kTransactionActive) {
562    Runtime::Current()->RecordWriteFieldChar(this, field_offset,
563                                           GetFieldShort<kVerifyFlags, kIsVolatile>(field_offset),
564                                           kIsVolatile);
565  }
566  if (kVerifyFlags & kVerifyThis) {
567    VerifyObject(this);
568  }
569  SetField<int16_t, kIsVolatile>(field_offset, new_value);
570}
571
572template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
573inline void Object::SetFieldCharVolatile(MemberOffset field_offset, uint16_t new_value) {
574  return SetFieldChar<kTransactionActive, kCheckTransaction, kVerifyFlags, true>(
575      field_offset, new_value);
576}
577
578template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
579inline void Object::SetFieldShortVolatile(MemberOffset field_offset, int16_t new_value) {
580  return SetFieldShort<kTransactionActive, kCheckTransaction, kVerifyFlags, true>(
581      field_offset, new_value);
582}
583
584template<VerifyObjectFlags kVerifyFlags, bool kIsVolatile>
585inline int32_t Object::GetField32(MemberOffset field_offset) {
586  if (kVerifyFlags & kVerifyThis) {
587    VerifyObject(this);
588  }
589  return GetField<int32_t, kIsVolatile>(field_offset);
590}
591
592template<VerifyObjectFlags kVerifyFlags>
593inline int32_t Object::GetField32Volatile(MemberOffset field_offset) {
594  return GetField32<kVerifyFlags, true>(field_offset);
595}
596
597template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags,
598    bool kIsVolatile>
599inline void Object::SetField32(MemberOffset field_offset, int32_t new_value) {
600  if (kCheckTransaction) {
601    DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
602  }
603  if (kTransactionActive) {
604    Runtime::Current()->RecordWriteField32(this, field_offset,
605                                           GetField32<kVerifyFlags, kIsVolatile>(field_offset),
606                                           kIsVolatile);
607  }
608  if (kVerifyFlags & kVerifyThis) {
609    VerifyObject(this);
610  }
611  SetField<int32_t, kIsVolatile>(field_offset, new_value);
612}
613
614template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
615inline void Object::SetField32Volatile(MemberOffset field_offset, int32_t new_value) {
616  SetField32<kTransactionActive, kCheckTransaction, kVerifyFlags, true>(field_offset, new_value);
617}
618
619// TODO: Pass memory_order_ and strong/weak as arguments to avoid code duplication?
620
621template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
622inline bool Object::CasFieldWeakSequentiallyConsistent32(MemberOffset field_offset,
623                                                         int32_t old_value, int32_t new_value) {
624  if (kCheckTransaction) {
625    DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
626  }
627  if (kTransactionActive) {
628    Runtime::Current()->RecordWriteField32(this, field_offset, old_value, true);
629  }
630  if (kVerifyFlags & kVerifyThis) {
631    VerifyObject(this);
632  }
633  uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
634  AtomicInteger* atomic_addr = reinterpret_cast<AtomicInteger*>(raw_addr);
635
636  return atomic_addr->CompareExchangeWeakSequentiallyConsistent(old_value, new_value);
637}
638
639template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
640inline bool Object::CasFieldWeakRelaxed32(MemberOffset field_offset,
641                                          int32_t old_value, int32_t new_value) {
642  if (kCheckTransaction) {
643    DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
644  }
645  if (kTransactionActive) {
646    Runtime::Current()->RecordWriteField32(this, field_offset, old_value, true);
647  }
648  if (kVerifyFlags & kVerifyThis) {
649    VerifyObject(this);
650  }
651  uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
652  AtomicInteger* atomic_addr = reinterpret_cast<AtomicInteger*>(raw_addr);
653
654  return atomic_addr->CompareExchangeWeakRelaxed(old_value, new_value);
655}
656
657template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
658inline bool Object::CasFieldStrongSequentiallyConsistent32(MemberOffset field_offset,
659                                                           int32_t old_value, int32_t new_value) {
660  if (kCheckTransaction) {
661    DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
662  }
663  if (kTransactionActive) {
664    Runtime::Current()->RecordWriteField32(this, field_offset, old_value, true);
665  }
666  if (kVerifyFlags & kVerifyThis) {
667    VerifyObject(this);
668  }
669  uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
670  AtomicInteger* atomic_addr = reinterpret_cast<AtomicInteger*>(raw_addr);
671
672  return atomic_addr->CompareExchangeStrongSequentiallyConsistent(old_value, new_value);
673}
674
675template<VerifyObjectFlags kVerifyFlags, bool kIsVolatile>
676inline int64_t Object::GetField64(MemberOffset field_offset) {
677  if (kVerifyFlags & kVerifyThis) {
678    VerifyObject(this);
679  }
680  return GetField<int64_t, kIsVolatile>(field_offset);
681}
682
683template<VerifyObjectFlags kVerifyFlags>
684inline int64_t Object::GetField64Volatile(MemberOffset field_offset) {
685  return GetField64<kVerifyFlags, true>(field_offset);
686}
687
688template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags,
689    bool kIsVolatile>
690inline void Object::SetField64(MemberOffset field_offset, int64_t new_value) {
691  if (kCheckTransaction) {
692    DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
693  }
694  if (kTransactionActive) {
695    Runtime::Current()->RecordWriteField64(this, field_offset,
696                                           GetField64<kVerifyFlags, kIsVolatile>(field_offset),
697                                           kIsVolatile);
698  }
699  if (kVerifyFlags & kVerifyThis) {
700    VerifyObject(this);
701  }
702  SetField<int64_t, kIsVolatile>(field_offset, new_value);
703}
704
705template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
706inline void Object::SetField64Volatile(MemberOffset field_offset, int64_t new_value) {
707  return SetField64<kTransactionActive, kCheckTransaction, kVerifyFlags, true>(field_offset,
708                                                                               new_value);
709}
710
711template<typename kSize, bool kIsVolatile>
712inline void Object::SetField(MemberOffset field_offset, kSize new_value) {
713  uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
714  kSize* addr = reinterpret_cast<kSize*>(raw_addr);
715  if (kIsVolatile) {
716    reinterpret_cast<Atomic<kSize>*>(addr)->StoreSequentiallyConsistent(new_value);
717  } else {
718    reinterpret_cast<Atomic<kSize>*>(addr)->StoreJavaData(new_value);
719  }
720}
721
722template<typename kSize, bool kIsVolatile>
723inline kSize Object::GetField(MemberOffset field_offset) {
724  const uint8_t* raw_addr = reinterpret_cast<const uint8_t*>(this) + field_offset.Int32Value();
725  const kSize* addr = reinterpret_cast<const kSize*>(raw_addr);
726  if (kIsVolatile) {
727    return reinterpret_cast<const Atomic<kSize>*>(addr)->LoadSequentiallyConsistent();
728  } else {
729    return reinterpret_cast<const Atomic<kSize>*>(addr)->LoadJavaData();
730  }
731}
732
733template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
734inline bool Object::CasFieldWeakSequentiallyConsistent64(MemberOffset field_offset,
735                                                         int64_t old_value, int64_t new_value) {
736  if (kCheckTransaction) {
737    DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
738  }
739  if (kTransactionActive) {
740    Runtime::Current()->RecordWriteField64(this, field_offset, old_value, true);
741  }
742  if (kVerifyFlags & kVerifyThis) {
743    VerifyObject(this);
744  }
745  uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
746  Atomic<int64_t>* atomic_addr = reinterpret_cast<Atomic<int64_t>*>(raw_addr);
747  return atomic_addr->CompareExchangeWeakSequentiallyConsistent(old_value, new_value);
748}
749
750template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
751inline bool Object::CasFieldStrongSequentiallyConsistent64(MemberOffset field_offset,
752                                                           int64_t old_value, int64_t new_value) {
753  if (kCheckTransaction) {
754    DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
755  }
756  if (kTransactionActive) {
757    Runtime::Current()->RecordWriteField64(this, field_offset, old_value, true);
758  }
759  if (kVerifyFlags & kVerifyThis) {
760    VerifyObject(this);
761  }
762  uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
763  Atomic<int64_t>* atomic_addr = reinterpret_cast<Atomic<int64_t>*>(raw_addr);
764  return atomic_addr->CompareExchangeStrongSequentiallyConsistent(old_value, new_value);
765}
766
767template<class T, VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption,
768         bool kIsVolatile>
769inline T* Object::GetFieldObject(MemberOffset field_offset) {
770  if (kVerifyFlags & kVerifyThis) {
771    VerifyObject(this);
772  }
773  uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
774  HeapReference<T>* objref_addr = reinterpret_cast<HeapReference<T>*>(raw_addr);
775  T* result = ReadBarrier::Barrier<T, kReadBarrierOption>(this, field_offset, objref_addr);
776  if (kIsVolatile) {
777    // TODO: Refactor to use a SequentiallyConsistent load instead.
778    QuasiAtomic::ThreadFenceAcquire();  // Ensure visibility of operations preceding store.
779  }
780  if (kVerifyFlags & kVerifyReads) {
781    VerifyObject(result);
782  }
783  return result;
784}
785
786template<class T, VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
787inline T* Object::GetFieldObjectVolatile(MemberOffset field_offset) {
788  return GetFieldObject<T, kVerifyFlags, kReadBarrierOption, true>(field_offset);
789}
790
791template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags,
792    bool kIsVolatile>
793inline void Object::SetFieldObjectWithoutWriteBarrier(MemberOffset field_offset,
794                                                      Object* new_value) {
795  if (kCheckTransaction) {
796    DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
797  }
798  if (kTransactionActive) {
799    mirror::Object* obj;
800    if (kIsVolatile) {
801      obj = GetFieldObjectVolatile<Object>(field_offset);
802    } else {
803      obj = GetFieldObject<Object>(field_offset);
804    }
805    Runtime::Current()->RecordWriteFieldReference(this, field_offset, obj, true);
806  }
807  if (kVerifyFlags & kVerifyThis) {
808    VerifyObject(this);
809  }
810  if (kVerifyFlags & kVerifyWrites) {
811    VerifyObject(new_value);
812  }
813  uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
814  HeapReference<Object>* objref_addr = reinterpret_cast<HeapReference<Object>*>(raw_addr);
815  if (kIsVolatile) {
816    // TODO: Refactor to use a SequentiallyConsistent store instead.
817    QuasiAtomic::ThreadFenceRelease();  // Ensure that prior accesses are visible before store.
818    objref_addr->Assign(new_value);
819    QuasiAtomic::ThreadFenceSequentiallyConsistent();
820                                // Ensure this store occurs before any volatile loads.
821  } else {
822    objref_addr->Assign(new_value);
823  }
824}
825
826template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags,
827    bool kIsVolatile>
828inline void Object::SetFieldObject(MemberOffset field_offset, Object* new_value) {
829  SetFieldObjectWithoutWriteBarrier<kTransactionActive, kCheckTransaction, kVerifyFlags,
830      kIsVolatile>(field_offset, new_value);
831  if (new_value != nullptr) {
832    Runtime::Current()->GetHeap()->WriteBarrierField(this, field_offset, new_value);
833    // TODO: Check field assignment could theoretically cause thread suspension, TODO: fix this.
834    CheckFieldAssignment(field_offset, new_value);
835  }
836}
837
838template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
839inline void Object::SetFieldObjectVolatile(MemberOffset field_offset, Object* new_value) {
840  SetFieldObject<kTransactionActive, kCheckTransaction, kVerifyFlags, true>(field_offset,
841                                                                            new_value);
842}
843
844template <VerifyObjectFlags kVerifyFlags>
845inline HeapReference<Object>* Object::GetFieldObjectReferenceAddr(MemberOffset field_offset) {
846  if (kVerifyFlags & kVerifyThis) {
847    VerifyObject(this);
848  }
849  return reinterpret_cast<HeapReference<Object>*>(reinterpret_cast<uint8_t*>(this) +
850      field_offset.Int32Value());
851}
852
853template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
854inline bool Object::CasFieldWeakSequentiallyConsistentObject(MemberOffset field_offset,
855                                                             Object* old_value, Object* new_value) {
856  bool success = CasFieldWeakSequentiallyConsistentObjectWithoutWriteBarrier<
857      kTransactionActive, kCheckTransaction, kVerifyFlags>(field_offset, old_value, new_value);
858  if (success) {
859    Runtime::Current()->GetHeap()->WriteBarrierField(this, field_offset, new_value);
860  }
861  return success;
862}
863
864template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
865inline bool Object::CasFieldWeakSequentiallyConsistentObjectWithoutWriteBarrier(
866    MemberOffset field_offset, Object* old_value, Object* new_value) {
867  if (kCheckTransaction) {
868    DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
869  }
870  if (kVerifyFlags & kVerifyThis) {
871    VerifyObject(this);
872  }
873  if (kVerifyFlags & kVerifyWrites) {
874    VerifyObject(new_value);
875  }
876  if (kVerifyFlags & kVerifyReads) {
877    VerifyObject(old_value);
878  }
879  if (kTransactionActive) {
880    Runtime::Current()->RecordWriteFieldReference(this, field_offset, old_value, true);
881  }
882  HeapReference<Object> old_ref(HeapReference<Object>::FromMirrorPtr(old_value));
883  HeapReference<Object> new_ref(HeapReference<Object>::FromMirrorPtr(new_value));
884  uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
885  Atomic<uint32_t>* atomic_addr = reinterpret_cast<Atomic<uint32_t>*>(raw_addr);
886
887  bool success = atomic_addr->CompareExchangeWeakSequentiallyConsistent(old_ref.reference_,
888                                                                        new_ref.reference_);
889  return success;
890}
891
892template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
893inline bool Object::CasFieldStrongSequentiallyConsistentObject(MemberOffset field_offset,
894                                                               Object* old_value, Object* new_value) {
895  bool success = CasFieldStrongSequentiallyConsistentObjectWithoutWriteBarrier<
896      kTransactionActive, kCheckTransaction, kVerifyFlags>(field_offset, old_value, new_value);
897  if (success) {
898    Runtime::Current()->GetHeap()->WriteBarrierField(this, field_offset, new_value);
899  }
900  return success;
901}
902
903template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
904inline bool Object::CasFieldStrongSequentiallyConsistentObjectWithoutWriteBarrier(
905    MemberOffset field_offset, Object* old_value, Object* new_value) {
906  if (kCheckTransaction) {
907    DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
908  }
909  if (kVerifyFlags & kVerifyThis) {
910    VerifyObject(this);
911  }
912  if (kVerifyFlags & kVerifyWrites) {
913    VerifyObject(new_value);
914  }
915  if (kVerifyFlags & kVerifyReads) {
916    VerifyObject(old_value);
917  }
918  if (kTransactionActive) {
919    Runtime::Current()->RecordWriteFieldReference(this, field_offset, old_value, true);
920  }
921  HeapReference<Object> old_ref(HeapReference<Object>::FromMirrorPtr(old_value));
922  HeapReference<Object> new_ref(HeapReference<Object>::FromMirrorPtr(new_value));
923  uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
924  Atomic<uint32_t>* atomic_addr = reinterpret_cast<Atomic<uint32_t>*>(raw_addr);
925
926  bool success = atomic_addr->CompareExchangeStrongSequentiallyConsistent(old_ref.reference_,
927                                                                          new_ref.reference_);
928  return success;
929}
930
931template<bool kVisitClass, bool kIsStatic, typename Visitor>
932inline void Object::VisitFieldsReferences(uint32_t ref_offsets, const Visitor& visitor) {
933  if (!kIsStatic && (ref_offsets != mirror::Class::kClassWalkSuper)) {
934    // Instance fields and not the slow-path.
935    if (kVisitClass) {
936      visitor(this, ClassOffset(), kIsStatic);
937    }
938    uint32_t field_offset = mirror::kObjectHeaderSize;
939    while (ref_offsets != 0) {
940      if ((ref_offsets & 1) != 0) {
941        visitor(this, MemberOffset(field_offset), kIsStatic);
942      }
943      ref_offsets >>= 1;
944      field_offset += sizeof(mirror::HeapReference<mirror::Object>);
945    }
946  } else {
947    // There is no reference offset bitmap. In the non-static case, walk up the class
948    // inheritance hierarchy and find reference offsets the hard way. In the static case, just
949    // consider this class.
950    for (mirror::Class* klass = kIsStatic ? AsClass() : GetClass(); klass != nullptr;
951        klass = kIsStatic ? nullptr : klass->GetSuperClass()) {
952      size_t num_reference_fields =
953          kIsStatic ? klass->NumReferenceStaticFields() : klass->NumReferenceInstanceFields();
954      if (num_reference_fields == 0u) {
955        continue;
956      }
957      MemberOffset field_offset = kIsStatic
958          ? klass->GetFirstReferenceStaticFieldOffset()
959          : klass->GetFirstReferenceInstanceFieldOffset();
960      for (size_t i = 0; i < num_reference_fields; ++i) {
961        // TODO: Do a simpler check?
962        if (kVisitClass || field_offset.Uint32Value() != ClassOffset().Uint32Value()) {
963          visitor(this, field_offset, kIsStatic);
964        }
965        field_offset = MemberOffset(field_offset.Uint32Value() +
966                                    sizeof(mirror::HeapReference<mirror::Object>));
967      }
968    }
969  }
970}
971
972template<bool kVisitClass, typename Visitor>
973inline void Object::VisitInstanceFieldsReferences(mirror::Class* klass, const Visitor& visitor) {
974  VisitFieldsReferences<kVisitClass, false>(
975      klass->GetReferenceInstanceOffsets<kVerifyNone>(), visitor);
976}
977
978template<bool kVisitClass, typename Visitor>
979inline void Object::VisitStaticFieldsReferences(mirror::Class* klass, const Visitor& visitor) {
980  DCHECK(!klass->IsTemp());
981  klass->VisitFieldsReferences<kVisitClass, true>(0, visitor);
982}
983
984template <const bool kVisitClass, VerifyObjectFlags kVerifyFlags, typename Visitor,
985    typename JavaLangRefVisitor>
986inline void Object::VisitReferences(const Visitor& visitor,
987                                    const JavaLangRefVisitor& ref_visitor) {
988  mirror::Class* klass = GetClass<kVerifyFlags>();
989  if (klass == Class::GetJavaLangClass()) {
990    AsClass<kVerifyNone>()->VisitReferences<kVisitClass>(klass, visitor);
991  } else if (klass->IsArrayClass() || klass->IsStringClass()) {
992    if (klass->IsObjectArrayClass<kVerifyNone>()) {
993      AsObjectArray<mirror::Object, kVerifyNone>()->VisitReferences<kVisitClass>(visitor);
994    } else if (kVisitClass) {
995      visitor(this, ClassOffset(), false);
996    }
997  } else {
998    DCHECK(!klass->IsVariableSize());
999    VisitInstanceFieldsReferences<kVisitClass>(klass, visitor);
1000    if (UNLIKELY(klass->IsTypeOfReferenceClass<kVerifyNone>())) {
1001      ref_visitor(klass, AsReference());
1002    }
1003  }
1004}
1005}  // namespace mirror
1006}  // namespace art
1007
1008#endif  // ART_RUNTIME_MIRROR_OBJECT_INL_H_
1009