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