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