object-inl.h revision 2c4257be8191c5eefde744e8965fcefc80a0a97d
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, 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  UNREACHABLE();
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  UNREACHABLE();
138#endif
139}
140
141inline bool Object::AtomicSetReadBarrierPointer(Object* expected_rb_ptr, Object* rb_ptr) {
142#ifdef USE_BAKER_OR_BROOKS_READ_BARRIER
143  DCHECK(kUseBakerOrBrooksReadBarrier);
144  MemberOffset offset = OFFSET_OF_OBJECT_MEMBER(Object, x_rb_ptr_);
145  uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + offset.SizeValue();
146  Atomic<uint32_t>* atomic_rb_ptr = reinterpret_cast<Atomic<uint32_t>*>(raw_addr);
147  HeapReference<Object> expected_ref(HeapReference<Object>::FromMirrorPtr(expected_rb_ptr));
148  HeapReference<Object> new_ref(HeapReference<Object>::FromMirrorPtr(rb_ptr));
149  do {
150    if (UNLIKELY(atomic_rb_ptr->LoadRelaxed() != expected_ref.reference_)) {
151      // Lost the race.
152      return false;
153    }
154  } while (!atomic_rb_ptr->CompareExchangeWeakSequentiallyConsistent(expected_ref.reference_,
155                                                                     new_ref.reference_));
156  DCHECK_EQ(new_ref.reference_, atomic_rb_ptr->LoadRelaxed());
157  return true;
158#else
159  LOG(FATAL) << "Unreachable";
160  UNREACHABLE();
161#endif
162}
163
164inline void Object::AssertReadBarrierPointer() const {
165  if (kUseBakerReadBarrier) {
166    Object* obj = const_cast<Object*>(this);
167    DCHECK(obj->GetReadBarrierPointer() == nullptr)
168        << "Bad Baker pointer: obj=" << reinterpret_cast<void*>(obj)
169        << " ptr=" << reinterpret_cast<void*>(obj->GetReadBarrierPointer());
170  } else {
171    CHECK(kUseBrooksReadBarrier);
172    Object* obj = const_cast<Object*>(this);
173    DCHECK_EQ(obj, obj->GetReadBarrierPointer())
174        << "Bad Brooks pointer: obj=" << reinterpret_cast<void*>(obj)
175        << " ptr=" << reinterpret_cast<void*>(obj->GetReadBarrierPointer());
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 uint8_t Object::GetFieldBoolean(MemberOffset field_offset) {
412  if (kVerifyFlags & kVerifyThis) {
413    VerifyObject(this);
414  }
415  return GetField<uint8_t, kIsVolatile>(field_offset);
416}
417
418template<VerifyObjectFlags kVerifyFlags, bool kIsVolatile>
419inline int8_t Object::GetFieldByte(MemberOffset field_offset) {
420  if (kVerifyFlags & kVerifyThis) {
421    VerifyObject(this);
422  }
423  return GetField<int8_t, kIsVolatile>(field_offset);
424}
425
426template<VerifyObjectFlags kVerifyFlags>
427inline uint8_t Object::GetFieldBooleanVolatile(MemberOffset field_offset) {
428  return GetFieldBoolean<kVerifyFlags, true>(field_offset);
429}
430
431template<VerifyObjectFlags kVerifyFlags>
432inline int8_t Object::GetFieldByteVolatile(MemberOffset field_offset) {
433  return GetFieldByte<kVerifyFlags, true>(field_offset);
434}
435
436template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags,
437    bool kIsVolatile>
438inline void Object::SetFieldBoolean(MemberOffset field_offset, uint8_t new_value)
439    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
440  if (kCheckTransaction) {
441    DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
442  }
443  if (kTransactionActive) {
444    Runtime::Current()->RecordWriteFieldBoolean(this, field_offset,
445                                           GetFieldBoolean<kVerifyFlags, kIsVolatile>(field_offset),
446                                           kIsVolatile);
447  }
448  if (kVerifyFlags & kVerifyThis) {
449    VerifyObject(this);
450  }
451  SetField<uint8_t, kIsVolatile>(field_offset, new_value);
452}
453
454template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags,
455    bool kIsVolatile>
456inline void Object::SetFieldByte(MemberOffset field_offset, int8_t new_value)
457    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
458  if (kCheckTransaction) {
459    DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
460  }
461  if (kTransactionActive) {
462    Runtime::Current()->RecordWriteFieldByte(this, field_offset,
463                                           GetFieldByte<kVerifyFlags, kIsVolatile>(field_offset),
464                                           kIsVolatile);
465  }
466  if (kVerifyFlags & kVerifyThis) {
467    VerifyObject(this);
468  }
469  SetField<int8_t, kIsVolatile>(field_offset, new_value);
470}
471
472template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
473inline void Object::SetFieldBooleanVolatile(MemberOffset field_offset, uint8_t new_value) {
474  return SetFieldBoolean<kTransactionActive, kCheckTransaction, kVerifyFlags, true>(
475      field_offset, new_value);
476}
477
478template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
479inline void Object::SetFieldByteVolatile(MemberOffset field_offset, int8_t new_value) {
480  return SetFieldByte<kTransactionActive, kCheckTransaction, kVerifyFlags, true>(
481      field_offset, new_value);
482}
483
484template<VerifyObjectFlags kVerifyFlags, bool kIsVolatile>
485inline uint16_t Object::GetFieldChar(MemberOffset field_offset) {
486  if (kVerifyFlags & kVerifyThis) {
487    VerifyObject(this);
488  }
489  return GetField<uint16_t, kIsVolatile>(field_offset);
490}
491
492template<VerifyObjectFlags kVerifyFlags, bool kIsVolatile>
493inline int16_t Object::GetFieldShort(MemberOffset field_offset) {
494  if (kVerifyFlags & kVerifyThis) {
495    VerifyObject(this);
496  }
497  return GetField<int16_t, kIsVolatile>(field_offset);
498}
499
500template<VerifyObjectFlags kVerifyFlags>
501inline uint16_t Object::GetFieldCharVolatile(MemberOffset field_offset) {
502  return GetFieldChar<kVerifyFlags, true>(field_offset);
503}
504
505template<VerifyObjectFlags kVerifyFlags>
506inline int16_t Object::GetFieldShortVolatile(MemberOffset field_offset) {
507  return GetFieldShort<kVerifyFlags, true>(field_offset);
508}
509
510template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags,
511    bool kIsVolatile>
512inline void Object::SetFieldChar(MemberOffset field_offset, uint16_t new_value) {
513  if (kCheckTransaction) {
514    DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
515  }
516  if (kTransactionActive) {
517    Runtime::Current()->RecordWriteFieldChar(this, field_offset,
518                                           GetFieldChar<kVerifyFlags, kIsVolatile>(field_offset),
519                                           kIsVolatile);
520  }
521  if (kVerifyFlags & kVerifyThis) {
522    VerifyObject(this);
523  }
524  SetField<uint16_t, kIsVolatile>(field_offset, new_value);
525}
526
527template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags,
528    bool kIsVolatile>
529inline void Object::SetFieldShort(MemberOffset field_offset, int16_t new_value) {
530  if (kCheckTransaction) {
531    DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
532  }
533  if (kTransactionActive) {
534    Runtime::Current()->RecordWriteFieldChar(this, field_offset,
535                                           GetFieldShort<kVerifyFlags, kIsVolatile>(field_offset),
536                                           kIsVolatile);
537  }
538  if (kVerifyFlags & kVerifyThis) {
539    VerifyObject(this);
540  }
541  SetField<int16_t, kIsVolatile>(field_offset, new_value);
542}
543
544template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
545inline void Object::SetFieldCharVolatile(MemberOffset field_offset, uint16_t new_value) {
546  return SetFieldChar<kTransactionActive, kCheckTransaction, kVerifyFlags, true>(
547      field_offset, new_value);
548}
549
550template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
551inline void Object::SetFieldShortVolatile(MemberOffset field_offset, int16_t new_value) {
552  return SetFieldShort<kTransactionActive, kCheckTransaction, kVerifyFlags, true>(
553      field_offset, new_value);
554}
555
556template<VerifyObjectFlags kVerifyFlags, bool kIsVolatile>
557inline int32_t Object::GetField32(MemberOffset field_offset) {
558  if (kVerifyFlags & kVerifyThis) {
559    VerifyObject(this);
560  }
561  return GetField<int32_t, kIsVolatile>(field_offset);
562}
563
564template<VerifyObjectFlags kVerifyFlags>
565inline int32_t Object::GetField32Volatile(MemberOffset field_offset) {
566  return GetField32<kVerifyFlags, true>(field_offset);
567}
568
569template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags,
570    bool kIsVolatile>
571inline void Object::SetField32(MemberOffset field_offset, int32_t new_value) {
572  if (kCheckTransaction) {
573    DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
574  }
575  if (kTransactionActive) {
576    Runtime::Current()->RecordWriteField32(this, field_offset,
577                                           GetField32<kVerifyFlags, kIsVolatile>(field_offset),
578                                           kIsVolatile);
579  }
580  if (kVerifyFlags & kVerifyThis) {
581    VerifyObject(this);
582  }
583  SetField<int32_t, kIsVolatile>(field_offset, new_value);
584}
585
586template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
587inline void Object::SetField32Volatile(MemberOffset field_offset, int32_t new_value) {
588  SetField32<kTransactionActive, kCheckTransaction, kVerifyFlags, true>(field_offset, new_value);
589}
590
591// TODO: Pass memory_order_ and strong/weak as arguments to avoid code duplication?
592
593template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
594inline bool Object::CasFieldWeakSequentiallyConsistent32(MemberOffset field_offset,
595                                                         int32_t old_value, int32_t new_value) {
596  if (kCheckTransaction) {
597    DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
598  }
599  if (kTransactionActive) {
600    Runtime::Current()->RecordWriteField32(this, field_offset, old_value, true);
601  }
602  if (kVerifyFlags & kVerifyThis) {
603    VerifyObject(this);
604  }
605  uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
606  AtomicInteger* atomic_addr = reinterpret_cast<AtomicInteger*>(raw_addr);
607
608  return atomic_addr->CompareExchangeWeakSequentiallyConsistent(old_value, new_value);
609}
610
611template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
612inline bool Object::CasFieldWeakRelaxed32(MemberOffset field_offset,
613                                          int32_t old_value, int32_t new_value) {
614  if (kCheckTransaction) {
615    DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
616  }
617  if (kTransactionActive) {
618    Runtime::Current()->RecordWriteField32(this, field_offset, old_value, true);
619  }
620  if (kVerifyFlags & kVerifyThis) {
621    VerifyObject(this);
622  }
623  uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
624  AtomicInteger* atomic_addr = reinterpret_cast<AtomicInteger*>(raw_addr);
625
626  return atomic_addr->CompareExchangeWeakRelaxed(old_value, new_value);
627}
628
629template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
630inline bool Object::CasFieldStrongSequentiallyConsistent32(MemberOffset field_offset,
631                                                           int32_t old_value, int32_t new_value) {
632  if (kCheckTransaction) {
633    DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
634  }
635  if (kTransactionActive) {
636    Runtime::Current()->RecordWriteField32(this, field_offset, old_value, true);
637  }
638  if (kVerifyFlags & kVerifyThis) {
639    VerifyObject(this);
640  }
641  uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
642  AtomicInteger* atomic_addr = reinterpret_cast<AtomicInteger*>(raw_addr);
643
644  return atomic_addr->CompareExchangeStrongSequentiallyConsistent(old_value, new_value);
645}
646
647template<VerifyObjectFlags kVerifyFlags, bool kIsVolatile>
648inline int64_t Object::GetField64(MemberOffset field_offset) {
649  if (kVerifyFlags & kVerifyThis) {
650    VerifyObject(this);
651  }
652  return GetField<int64_t, kIsVolatile>(field_offset);
653}
654
655template<VerifyObjectFlags kVerifyFlags>
656inline int64_t Object::GetField64Volatile(MemberOffset field_offset) {
657  return GetField64<kVerifyFlags, true>(field_offset);
658}
659
660template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags,
661    bool kIsVolatile>
662inline void Object::SetField64(MemberOffset field_offset, int64_t new_value) {
663  if (kCheckTransaction) {
664    DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
665  }
666  if (kTransactionActive) {
667    Runtime::Current()->RecordWriteField64(this, field_offset,
668                                           GetField64<kVerifyFlags, kIsVolatile>(field_offset),
669                                           kIsVolatile);
670  }
671  if (kVerifyFlags & kVerifyThis) {
672    VerifyObject(this);
673  }
674  SetField<int64_t, kIsVolatile>(field_offset, new_value);
675}
676
677template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
678inline void Object::SetField64Volatile(MemberOffset field_offset, int64_t new_value) {
679  return SetField64<kTransactionActive, kCheckTransaction, kVerifyFlags, true>(field_offset,
680                                                                               new_value);
681}
682
683template<typename kSize, bool kIsVolatile>
684inline void Object::SetField(MemberOffset field_offset, kSize new_value) {
685  uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
686  kSize* addr = reinterpret_cast<kSize*>(raw_addr);
687  if (kIsVolatile) {
688    reinterpret_cast<Atomic<kSize>*>(addr)->StoreSequentiallyConsistent(new_value);
689  } else {
690    reinterpret_cast<Atomic<kSize>*>(addr)->StoreJavaData(new_value);
691  }
692}
693
694template<typename kSize, bool kIsVolatile>
695inline kSize Object::GetField(MemberOffset field_offset) {
696  const uint8_t* raw_addr = reinterpret_cast<const uint8_t*>(this) + field_offset.Int32Value();
697  const kSize* addr = reinterpret_cast<const kSize*>(raw_addr);
698  if (kIsVolatile) {
699    return reinterpret_cast<const Atomic<kSize>*>(addr)->LoadSequentiallyConsistent();
700  } else {
701    return reinterpret_cast<const Atomic<kSize>*>(addr)->LoadJavaData();
702  }
703}
704
705template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
706inline bool Object::CasFieldWeakSequentiallyConsistent64(MemberOffset field_offset,
707                                                         int64_t old_value, int64_t new_value) {
708  if (kCheckTransaction) {
709    DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
710  }
711  if (kTransactionActive) {
712    Runtime::Current()->RecordWriteField64(this, field_offset, old_value, true);
713  }
714  if (kVerifyFlags & kVerifyThis) {
715    VerifyObject(this);
716  }
717  uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
718  Atomic<int64_t>* atomic_addr = reinterpret_cast<Atomic<int64_t>*>(raw_addr);
719  return atomic_addr->CompareExchangeWeakSequentiallyConsistent(old_value, new_value);
720}
721
722template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
723inline bool Object::CasFieldStrongSequentiallyConsistent64(MemberOffset field_offset,
724                                                           int64_t old_value, int64_t new_value) {
725  if (kCheckTransaction) {
726    DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
727  }
728  if (kTransactionActive) {
729    Runtime::Current()->RecordWriteField64(this, field_offset, old_value, true);
730  }
731  if (kVerifyFlags & kVerifyThis) {
732    VerifyObject(this);
733  }
734  uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
735  Atomic<int64_t>* atomic_addr = reinterpret_cast<Atomic<int64_t>*>(raw_addr);
736  return atomic_addr->CompareExchangeStrongSequentiallyConsistent(old_value, new_value);
737}
738
739template<class T, VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption,
740         bool kIsVolatile>
741inline T* Object::GetFieldObject(MemberOffset field_offset) {
742  if (kVerifyFlags & kVerifyThis) {
743    VerifyObject(this);
744  }
745  uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
746  HeapReference<T>* objref_addr = reinterpret_cast<HeapReference<T>*>(raw_addr);
747  T* result = ReadBarrier::Barrier<T, kReadBarrierOption>(this, field_offset, objref_addr);
748  if (kIsVolatile) {
749    // TODO: Refactor to use a SequentiallyConsistent load instead.
750    QuasiAtomic::ThreadFenceAcquire();  // Ensure visibility of operations preceding store.
751  }
752  if (kVerifyFlags & kVerifyReads) {
753    VerifyObject(result);
754  }
755  return result;
756}
757
758template<class T, VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
759inline T* Object::GetFieldObjectVolatile(MemberOffset field_offset) {
760  return GetFieldObject<T, kVerifyFlags, kReadBarrierOption, true>(field_offset);
761}
762
763template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags,
764    bool kIsVolatile>
765inline void Object::SetFieldObjectWithoutWriteBarrier(MemberOffset field_offset,
766                                                      Object* new_value) {
767  if (kCheckTransaction) {
768    DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
769  }
770  if (kTransactionActive) {
771    mirror::Object* obj;
772    if (kIsVolatile) {
773      obj = GetFieldObjectVolatile<Object>(field_offset);
774    } else {
775      obj = GetFieldObject<Object>(field_offset);
776    }
777    Runtime::Current()->RecordWriteFieldReference(this, field_offset, obj, true);
778  }
779  if (kVerifyFlags & kVerifyThis) {
780    VerifyObject(this);
781  }
782  if (kVerifyFlags & kVerifyWrites) {
783    VerifyObject(new_value);
784  }
785  uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
786  HeapReference<Object>* objref_addr = reinterpret_cast<HeapReference<Object>*>(raw_addr);
787  if (kIsVolatile) {
788    // TODO: Refactor to use a SequentiallyConsistent store instead.
789    QuasiAtomic::ThreadFenceRelease();  // Ensure that prior accesses are visible before store.
790    objref_addr->Assign(new_value);
791    QuasiAtomic::ThreadFenceSequentiallyConsistent();
792                                // Ensure this store occurs before any volatile loads.
793  } else {
794    objref_addr->Assign(new_value);
795  }
796}
797
798template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags,
799    bool kIsVolatile>
800inline void Object::SetFieldObject(MemberOffset field_offset, Object* new_value) {
801  SetFieldObjectWithoutWriteBarrier<kTransactionActive, kCheckTransaction, kVerifyFlags,
802      kIsVolatile>(field_offset, new_value);
803  if (new_value != nullptr) {
804    Runtime::Current()->GetHeap()->WriteBarrierField(this, field_offset, new_value);
805    // TODO: Check field assignment could theoretically cause thread suspension, TODO: fix this.
806    CheckFieldAssignment(field_offset, new_value);
807  }
808}
809
810template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
811inline void Object::SetFieldObjectVolatile(MemberOffset field_offset, Object* new_value) {
812  SetFieldObject<kTransactionActive, kCheckTransaction, kVerifyFlags, true>(field_offset,
813                                                                            new_value);
814}
815
816template <VerifyObjectFlags kVerifyFlags>
817inline HeapReference<Object>* Object::GetFieldObjectReferenceAddr(MemberOffset field_offset) {
818  if (kVerifyFlags & kVerifyThis) {
819    VerifyObject(this);
820  }
821  return reinterpret_cast<HeapReference<Object>*>(reinterpret_cast<uint8_t*>(this) +
822      field_offset.Int32Value());
823}
824
825template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
826inline bool Object::CasFieldWeakSequentiallyConsistentObject(MemberOffset field_offset,
827                                                             Object* old_value, Object* new_value) {
828  if (kCheckTransaction) {
829    DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
830  }
831  if (kVerifyFlags & kVerifyThis) {
832    VerifyObject(this);
833  }
834  if (kVerifyFlags & kVerifyWrites) {
835    VerifyObject(new_value);
836  }
837  if (kVerifyFlags & kVerifyReads) {
838    VerifyObject(old_value);
839  }
840  if (kTransactionActive) {
841    Runtime::Current()->RecordWriteFieldReference(this, field_offset, old_value, true);
842  }
843  HeapReference<Object> old_ref(HeapReference<Object>::FromMirrorPtr(old_value));
844  HeapReference<Object> new_ref(HeapReference<Object>::FromMirrorPtr(new_value));
845  uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
846  Atomic<uint32_t>* atomic_addr = reinterpret_cast<Atomic<uint32_t>*>(raw_addr);
847
848  bool success = atomic_addr->CompareExchangeWeakSequentiallyConsistent(old_ref.reference_,
849                                                                        new_ref.reference_);
850
851  if (success) {
852    Runtime::Current()->GetHeap()->WriteBarrierField(this, field_offset, new_value);
853  }
854  return success;
855}
856
857template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
858inline bool Object::CasFieldStrongSequentiallyConsistentObject(MemberOffset field_offset,
859                                                             Object* old_value, Object* new_value) {
860  if (kCheckTransaction) {
861    DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
862  }
863  if (kVerifyFlags & kVerifyThis) {
864    VerifyObject(this);
865  }
866  if (kVerifyFlags & kVerifyWrites) {
867    VerifyObject(new_value);
868  }
869  if (kVerifyFlags & kVerifyReads) {
870    VerifyObject(old_value);
871  }
872  if (kTransactionActive) {
873    Runtime::Current()->RecordWriteFieldReference(this, field_offset, old_value, true);
874  }
875  HeapReference<Object> old_ref(HeapReference<Object>::FromMirrorPtr(old_value));
876  HeapReference<Object> new_ref(HeapReference<Object>::FromMirrorPtr(new_value));
877  uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
878  Atomic<uint32_t>* atomic_addr = reinterpret_cast<Atomic<uint32_t>*>(raw_addr);
879
880  bool success = atomic_addr->CompareExchangeStrongSequentiallyConsistent(old_ref.reference_,
881                                                                          new_ref.reference_);
882
883  if (success) {
884    Runtime::Current()->GetHeap()->WriteBarrierField(this, field_offset, new_value);
885  }
886  return success;
887}
888
889template<bool kVisitClass, bool kIsStatic, typename Visitor>
890inline void Object::VisitFieldsReferences(uint32_t ref_offsets, const Visitor& visitor) {
891  if (!kIsStatic && (ref_offsets != mirror::Class::kClassWalkSuper)) {
892    // Instance fields and not the slow-path.
893    if (kVisitClass) {
894      visitor(this, ClassOffset(), kIsStatic);
895    }
896    uint32_t field_offset = mirror::kObjectHeaderSize;
897    while (ref_offsets != 0) {
898      if ((ref_offsets & 1) != 0) {
899        visitor(this, MemberOffset(field_offset), kIsStatic);
900      }
901      ref_offsets >>= 1;
902      field_offset += sizeof(mirror::HeapReference<mirror::Object>);
903    }
904  } else {
905    // There is no reference offset bitmap. In the non-static case, walk up the class
906    // inheritance hierarchy and find reference offsets the hard way. In the static case, just
907    // consider this class.
908    for (mirror::Class* klass = kIsStatic ? AsClass() : GetClass(); klass != nullptr;
909        klass = kIsStatic ? nullptr : klass->GetSuperClass()) {
910      size_t num_reference_fields =
911          kIsStatic ? klass->NumReferenceStaticFields() : klass->NumReferenceInstanceFields();
912      for (size_t i = 0; i < num_reference_fields; ++i) {
913        mirror::ArtField* field = kIsStatic ? klass->GetStaticField(i) : klass->GetInstanceField(i);
914        MemberOffset field_offset = field->GetOffset();
915        // TODO: Do a simpler check?
916        if (kVisitClass || field_offset.Uint32Value() != ClassOffset().Uint32Value()) {
917          visitor(this, field_offset, kIsStatic);
918        }
919      }
920    }
921  }
922}
923
924template<bool kVisitClass, typename Visitor>
925inline void Object::VisitInstanceFieldsReferences(mirror::Class* klass, const Visitor& visitor) {
926  VisitFieldsReferences<kVisitClass, false>(
927      klass->GetReferenceInstanceOffsets<kVerifyNone>(), visitor);
928}
929
930template<bool kVisitClass, typename Visitor>
931inline void Object::VisitStaticFieldsReferences(mirror::Class* klass, const Visitor& visitor) {
932  DCHECK(!klass->IsTemp());
933  klass->VisitFieldsReferences<kVisitClass, true>(0, visitor);
934}
935
936template <const bool kVisitClass, VerifyObjectFlags kVerifyFlags, typename Visitor,
937    typename JavaLangRefVisitor>
938inline void Object::VisitReferences(const Visitor& visitor,
939                                    const JavaLangRefVisitor& ref_visitor) {
940  mirror::Class* klass = GetClass<kVerifyFlags>();
941  if (klass == Class::GetJavaLangClass()) {
942    AsClass<kVerifyNone>()->VisitReferences<kVisitClass>(klass, visitor);
943  } else if (klass->IsArrayClass()) {
944    if (klass->IsObjectArrayClass<kVerifyNone>()) {
945      AsObjectArray<mirror::Object, kVerifyNone>()->VisitReferences<kVisitClass>(visitor);
946    } else if (kVisitClass) {
947      visitor(this, ClassOffset(), false);
948    }
949  } else {
950    DCHECK(!klass->IsVariableSize());
951    VisitInstanceFieldsReferences<kVisitClass>(klass, visitor);
952    if (UNLIKELY(klass->IsTypeOfReferenceClass<kVerifyNone>())) {
953      ref_visitor(klass, AsReference());
954    }
955  }
956}
957
958}  // namespace mirror
959}  // namespace art
960
961#endif  // ART_RUNTIME_MIRROR_OBJECT_INL_H_
962