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