object-inl.h revision 61c5ebc6aee2cac1c363de6fbdac25ada1697fdb
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>()->IsArtFieldClass();
221}
222
223template<VerifyObjectFlags kVerifyFlags>
224inline ArtField* Object::AsArtField() {
225  DCHECK(IsArtField<kVerifyFlags>());
226  return down_cast<ArtField*>(this);
227}
228
229template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
230inline bool Object::IsArtMethod() {
231  return GetClass<kVerifyFlags, kReadBarrierOption>()->IsArtMethodClass();
232}
233
234template<VerifyObjectFlags kVerifyFlags>
235inline ArtMethod* Object::AsArtMethod() {
236  DCHECK(IsArtMethod<kVerifyFlags>());
237  return down_cast<ArtMethod*>(this);
238}
239
240template<VerifyObjectFlags kVerifyFlags>
241inline bool Object::IsReferenceInstance() {
242  return GetClass<kVerifyFlags>()->IsReferenceClass();
243}
244
245template<VerifyObjectFlags kVerifyFlags>
246inline Reference* Object::AsReference() {
247  DCHECK(IsReferenceInstance<kVerifyFlags>());
248  return down_cast<Reference*>(this);
249}
250
251template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
252inline Array* Object::AsArray() {
253  DCHECK((IsArrayInstance<kVerifyFlags, kReadBarrierOption>()));
254  return down_cast<Array*>(this);
255}
256
257template<VerifyObjectFlags kVerifyFlags>
258inline BooleanArray* Object::AsBooleanArray() {
259  constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
260  DCHECK(GetClass<kVerifyFlags>()->IsArrayClass());
261  DCHECK(GetClass<kNewFlags>()->GetComponentType()->IsPrimitiveBoolean());
262  return down_cast<BooleanArray*>(this);
263}
264
265template<VerifyObjectFlags kVerifyFlags>
266inline ByteArray* Object::AsByteArray() {
267  static const VerifyObjectFlags kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
268  DCHECK(GetClass<kVerifyFlags>()->IsArrayClass());
269  DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveByte());
270  return down_cast<ByteArray*>(this);
271}
272
273template<VerifyObjectFlags kVerifyFlags>
274inline ByteArray* Object::AsByteSizedArray() {
275  constexpr VerifyObjectFlags kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
276  DCHECK(GetClass<kVerifyFlags>()->IsArrayClass());
277  DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveByte() ||
278         GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveBoolean());
279  return down_cast<ByteArray*>(this);
280}
281
282template<VerifyObjectFlags kVerifyFlags>
283inline CharArray* Object::AsCharArray() {
284  constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
285  DCHECK(GetClass<kVerifyFlags>()->IsArrayClass());
286  DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveChar());
287  return down_cast<CharArray*>(this);
288}
289
290template<VerifyObjectFlags kVerifyFlags>
291inline ShortArray* Object::AsShortArray() {
292  constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
293  DCHECK(GetClass<kVerifyFlags>()->IsArrayClass());
294  DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveShort());
295  return down_cast<ShortArray*>(this);
296}
297
298template<VerifyObjectFlags kVerifyFlags>
299inline ShortArray* Object::AsShortSizedArray() {
300  constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
301  DCHECK(GetClass<kVerifyFlags>()->IsArrayClass());
302  DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveShort() ||
303         GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveChar());
304  return down_cast<ShortArray*>(this);
305}
306
307template<VerifyObjectFlags kVerifyFlags>
308inline IntArray* Object::AsIntArray() {
309  constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
310  DCHECK(GetClass<kVerifyFlags>()->IsArrayClass());
311  DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveInt() ||
312         GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveFloat());
313  return down_cast<IntArray*>(this);
314}
315
316template<VerifyObjectFlags kVerifyFlags>
317inline LongArray* Object::AsLongArray() {
318  constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
319  DCHECK(GetClass<kVerifyFlags>()->IsArrayClass());
320  DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveLong() ||
321         GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveDouble());
322  return down_cast<LongArray*>(this);
323}
324
325template<VerifyObjectFlags kVerifyFlags>
326inline FloatArray* Object::AsFloatArray() {
327  constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
328  DCHECK(GetClass<kVerifyFlags>()->IsArrayClass());
329  DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveFloat());
330  return down_cast<FloatArray*>(this);
331}
332
333template<VerifyObjectFlags kVerifyFlags>
334inline DoubleArray* Object::AsDoubleArray() {
335  constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
336  DCHECK(GetClass<kVerifyFlags>()->IsArrayClass());
337  DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveDouble());
338  return down_cast<DoubleArray*>(this);
339}
340
341template<VerifyObjectFlags kVerifyFlags>
342inline String* Object::AsString() {
343  DCHECK(GetClass<kVerifyFlags>()->IsStringClass());
344  return down_cast<String*>(this);
345}
346
347template<VerifyObjectFlags kVerifyFlags>
348inline Throwable* Object::AsThrowable() {
349  DCHECK(GetClass<kVerifyFlags>()->IsThrowableClass());
350  return down_cast<Throwable*>(this);
351}
352
353template<VerifyObjectFlags kVerifyFlags>
354inline bool Object::IsWeakReferenceInstance() {
355  return GetClass<kVerifyFlags>()->IsWeakReferenceClass();
356}
357
358template<VerifyObjectFlags kVerifyFlags>
359inline bool Object::IsSoftReferenceInstance() {
360  return GetClass<kVerifyFlags>()->IsSoftReferenceClass();
361}
362
363template<VerifyObjectFlags kVerifyFlags>
364inline bool Object::IsFinalizerReferenceInstance() {
365  return GetClass<kVerifyFlags>()->IsFinalizerReferenceClass();
366}
367
368template<VerifyObjectFlags kVerifyFlags>
369inline FinalizerReference* Object::AsFinalizerReference() {
370  DCHECK(IsFinalizerReferenceInstance<kVerifyFlags>());
371  return down_cast<FinalizerReference*>(this);
372}
373
374template<VerifyObjectFlags kVerifyFlags>
375inline bool Object::IsPhantomReferenceInstance() {
376  return GetClass<kVerifyFlags>()->IsPhantomReferenceClass();
377}
378
379template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
380inline size_t Object::SizeOf() {
381  size_t result;
382  constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
383  if (IsArrayInstance<kVerifyFlags, kReadBarrierOption>()) {
384    result = AsArray<kNewFlags, kReadBarrierOption>()->
385        template SizeOf<kNewFlags, kReadBarrierOption>();
386  } else if (IsClass<kNewFlags, kReadBarrierOption>()) {
387    result = AsClass<kNewFlags, kReadBarrierOption>()->
388        template SizeOf<kNewFlags, kReadBarrierOption>();
389  } else {
390    result = GetClass<kNewFlags, kReadBarrierOption>()->
391        template GetObjectSize<kNewFlags, kReadBarrierOption>();
392  }
393  DCHECK_GE(result, sizeof(Object))
394      << " class=" << PrettyTypeOf(GetClass<kNewFlags, kReadBarrierOption>());
395  DCHECK(!(IsArtField<kNewFlags, kReadBarrierOption>())  || result == sizeof(ArtField));
396  DCHECK(!(IsArtMethod<kNewFlags, kReadBarrierOption>()) || result == sizeof(ArtMethod));
397  return result;
398}
399
400template<VerifyObjectFlags kVerifyFlags, bool kIsVolatile>
401inline int32_t Object::GetField32(MemberOffset field_offset) {
402  if (kVerifyFlags & kVerifyThis) {
403    VerifyObject(this);
404  }
405  const byte* raw_addr = reinterpret_cast<const byte*>(this) + field_offset.Int32Value();
406  const int32_t* word_addr = reinterpret_cast<const int32_t*>(raw_addr);
407  if (UNLIKELY(kIsVolatile)) {
408    int32_t result = *(reinterpret_cast<volatile int32_t*>(const_cast<int32_t*>(word_addr)));
409    QuasiAtomic::MembarLoadLoad();  // Ensure volatile loads don't re-order.
410    return result;
411  } else {
412    return *word_addr;
413  }
414}
415
416template<VerifyObjectFlags kVerifyFlags>
417inline int32_t Object::GetField32Volatile(MemberOffset field_offset) {
418  return GetField32<kVerifyFlags, true>(field_offset);
419}
420
421template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags,
422    bool kIsVolatile>
423inline void Object::SetField32(MemberOffset field_offset, int32_t new_value) {
424  if (kCheckTransaction) {
425    DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
426  }
427  if (kTransactionActive) {
428    Runtime::Current()->RecordWriteField32(this, field_offset,
429                                           GetField32<kVerifyFlags, kIsVolatile>(field_offset),
430                                           kIsVolatile);
431  }
432  if (kVerifyFlags & kVerifyThis) {
433    VerifyObject(this);
434  }
435  byte* raw_addr = reinterpret_cast<byte*>(this) + field_offset.Int32Value();
436  int32_t* word_addr = reinterpret_cast<int32_t*>(raw_addr);
437  if (kIsVolatile) {
438    QuasiAtomic::MembarStoreStore();  // Ensure this store occurs after others in the queue.
439    *word_addr = new_value;
440    QuasiAtomic::MembarStoreLoad();  // Ensure this store occurs before any volatile loads.
441  } else {
442    *word_addr = new_value;
443  }
444}
445
446template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
447inline void Object::SetField32Volatile(MemberOffset field_offset, int32_t new_value) {
448  SetField32<kTransactionActive, kCheckTransaction, kVerifyFlags, true>(field_offset, new_value);
449}
450
451template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
452inline bool Object::CasField32(MemberOffset field_offset, int32_t old_value, int32_t new_value) {
453  if (kCheckTransaction) {
454    DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
455  }
456  if (kTransactionActive) {
457    Runtime::Current()->RecordWriteField32(this, field_offset, old_value, true);
458  }
459  if (kVerifyFlags & kVerifyThis) {
460    VerifyObject(this);
461  }
462  byte* raw_addr = reinterpret_cast<byte*>(this) + field_offset.Int32Value();
463  volatile int32_t* addr = reinterpret_cast<volatile int32_t*>(raw_addr);
464  return __sync_bool_compare_and_swap(addr, old_value, new_value);
465}
466
467template<VerifyObjectFlags kVerifyFlags, bool kIsVolatile>
468inline int64_t Object::GetField64(MemberOffset field_offset) {
469  if (kVerifyFlags & kVerifyThis) {
470    VerifyObject(this);
471  }
472  const byte* raw_addr = reinterpret_cast<const byte*>(this) + field_offset.Int32Value();
473  const int64_t* addr = reinterpret_cast<const int64_t*>(raw_addr);
474  if (kIsVolatile) {
475    int64_t result = QuasiAtomic::Read64(addr);
476    QuasiAtomic::MembarLoadLoad();  // Ensure volatile loads don't re-order.
477    return result;
478  } else {
479    return *addr;
480  }
481}
482
483template<VerifyObjectFlags kVerifyFlags>
484inline int64_t Object::GetField64Volatile(MemberOffset field_offset) {
485  return GetField64<kVerifyFlags, true>(field_offset);
486}
487
488template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags,
489    bool kIsVolatile>
490inline void Object::SetField64(MemberOffset field_offset, int64_t new_value) {
491  if (kCheckTransaction) {
492    DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
493  }
494  if (kTransactionActive) {
495    Runtime::Current()->RecordWriteField64(this, field_offset,
496                                           GetField64<kVerifyFlags, kIsVolatile>(field_offset),
497                                           kIsVolatile);
498  }
499  if (kVerifyFlags & kVerifyThis) {
500    VerifyObject(this);
501  }
502  byte* raw_addr = reinterpret_cast<byte*>(this) + field_offset.Int32Value();
503  int64_t* addr = reinterpret_cast<int64_t*>(raw_addr);
504  if (kIsVolatile) {
505    QuasiAtomic::MembarStoreStore();  // Ensure this store occurs after others in the queue.
506    QuasiAtomic::Write64(addr, new_value);
507    if (!QuasiAtomic::LongAtomicsUseMutexes()) {
508      QuasiAtomic::MembarStoreLoad();  // Ensure this store occurs before any volatile loads.
509    } else {
510      // Fence from from mutex is enough.
511    }
512  } else {
513    *addr = new_value;
514  }
515}
516
517template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
518inline void Object::SetField64Volatile(MemberOffset field_offset, int64_t new_value) {
519  return SetField64<kTransactionActive, kCheckTransaction, kVerifyFlags, true>(field_offset,
520                                                                               new_value);
521}
522
523template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
524inline bool Object::CasField64(MemberOffset field_offset, int64_t old_value, int64_t new_value) {
525  if (kCheckTransaction) {
526    DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
527  }
528  if (kTransactionActive) {
529    Runtime::Current()->RecordWriteField64(this, field_offset, old_value, true);
530  }
531  if (kVerifyFlags & kVerifyThis) {
532    VerifyObject(this);
533  }
534  byte* raw_addr = reinterpret_cast<byte*>(this) + field_offset.Int32Value();
535  volatile int64_t* addr = reinterpret_cast<volatile int64_t*>(raw_addr);
536  return QuasiAtomic::Cas64(old_value, new_value, addr);
537}
538
539template<class T, VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption,
540         bool kIsVolatile>
541inline T* Object::GetFieldObject(MemberOffset field_offset) {
542  if (kVerifyFlags & kVerifyThis) {
543    VerifyObject(this);
544  }
545  byte* raw_addr = reinterpret_cast<byte*>(this) + field_offset.Int32Value();
546  HeapReference<T>* objref_addr = reinterpret_cast<HeapReference<T>*>(raw_addr);
547  T* result = ReadBarrier::Barrier<T, kReadBarrierOption>(this, field_offset, objref_addr);
548  if (kIsVolatile) {
549    QuasiAtomic::MembarLoadLoad();  // Ensure loads don't re-order.
550  }
551  if (kVerifyFlags & kVerifyReads) {
552    VerifyObject(result);
553  }
554  return result;
555}
556
557template<class T, VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
558inline T* Object::GetFieldObjectVolatile(MemberOffset field_offset) {
559  return GetFieldObject<T, kVerifyFlags, kReadBarrierOption, true>(field_offset);
560}
561
562template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags,
563    bool kIsVolatile>
564inline void Object::SetFieldObjectWithoutWriteBarrier(MemberOffset field_offset,
565                                                      Object* new_value) {
566  if (kCheckTransaction) {
567    DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
568  }
569  if (kTransactionActive) {
570    mirror::Object* obj;
571    if (kIsVolatile) {
572      obj = GetFieldObjectVolatile<Object>(field_offset);
573    } else {
574      obj = GetFieldObject<Object>(field_offset);
575    }
576    Runtime::Current()->RecordWriteFieldReference(this, field_offset, obj, true);
577  }
578  if (kVerifyFlags & kVerifyThis) {
579    VerifyObject(this);
580  }
581  if (kVerifyFlags & kVerifyWrites) {
582    VerifyObject(new_value);
583  }
584  byte* raw_addr = reinterpret_cast<byte*>(this) + field_offset.Int32Value();
585  HeapReference<Object>* objref_addr = reinterpret_cast<HeapReference<Object>*>(raw_addr);
586  if (kIsVolatile) {
587    QuasiAtomic::MembarStoreStore();  // Ensure this store occurs after others in the queue.
588    objref_addr->Assign(new_value);
589    QuasiAtomic::MembarStoreLoad();  // Ensure this store occurs before any loads.
590  } else {
591    objref_addr->Assign(new_value);
592  }
593}
594
595template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags,
596    bool kIsVolatile>
597inline void Object::SetFieldObject(MemberOffset field_offset, Object* new_value) {
598  SetFieldObjectWithoutWriteBarrier<kTransactionActive, kCheckTransaction, kVerifyFlags,
599      kIsVolatile>(field_offset, new_value);
600  if (new_value != nullptr) {
601    Runtime::Current()->GetHeap()->WriteBarrierField(this, field_offset, new_value);
602    // TODO: Check field assignment could theoretically cause thread suspension, TODO: fix this.
603    CheckFieldAssignment(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