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