• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  
35  namespace art {
36  namespace mirror {
37  
ClassSize()38  inline uint32_t Object::ClassSize() {
39    uint32_t vtable_entries = kVTableLength;
40    return Class::ComputeClassSize(true, vtable_entries, 0, 0, 0);
41  }
42  
43  template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
GetClass()44  inline Class* Object::GetClass() {
45    return GetFieldObject<Class, kVerifyFlags, kReadBarrierOption>(
46        OFFSET_OF_OBJECT_MEMBER(Object, klass_));
47  }
48  
49  template<VerifyObjectFlags kVerifyFlags>
SetClass(Class * new_klass)50  inline 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  
GetLockWord(bool as_volatile)61  inline 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  
SetLockWord(LockWord new_val,bool as_volatile)68  inline 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  
CasLockWordWeakSequentiallyConsistent(LockWord old_val,LockWord new_val)77  inline 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  
CasLockWordWeakRelaxed(LockWord old_val,LockWord new_val)83  inline 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  
GetLockOwnerThreadId()89  inline uint32_t Object::GetLockOwnerThreadId() {
90    return Monitor::GetLockOwnerThreadId(this);
91  }
92  
MonitorEnter(Thread * self)93  inline mirror::Object* Object::MonitorEnter(Thread* self) {
94    return Monitor::MonitorEnter(self, this);
95  }
96  
MonitorExit(Thread * self)97  inline bool Object::MonitorExit(Thread* self) {
98    return Monitor::MonitorExit(self, this);
99  }
100  
Notify(Thread * self)101  inline void Object::Notify(Thread* self) {
102    Monitor::Notify(self, this);
103  }
104  
NotifyAll(Thread * self)105  inline void Object::NotifyAll(Thread* self) {
106    Monitor::NotifyAll(self, this);
107  }
108  
Wait(Thread * self)109  inline void Object::Wait(Thread* self) {
110    Monitor::Wait(self, this, 0, 0, true, kWaiting);
111  }
112  
Wait(Thread * self,int64_t ms,int32_t ns)113  inline void Object::Wait(Thread* self, int64_t ms, int32_t ns) {
114    Monitor::Wait(self, this, ms, ns, true, kTimedWaiting);
115  }
116  
GetReadBarrierPointer()117  inline 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  
SetReadBarrierPointer(Object * rb_ptr)128  inline 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  
AtomicSetReadBarrierPointer(Object * expected_rb_ptr,Object * rb_ptr)140  inline 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  
AssertReadBarrierPointer()163  inline 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  
179  template<VerifyObjectFlags kVerifyFlags>
VerifierInstanceOf(Class * klass)180  inline bool Object::VerifierInstanceOf(Class* klass) {
181    DCHECK(klass != NULL);
182    DCHECK(GetClass<kVerifyFlags>() != NULL);
183    return klass->IsInterface() || InstanceOf(klass);
184  }
185  
186  template<VerifyObjectFlags kVerifyFlags>
InstanceOf(Class * klass)187  inline bool Object::InstanceOf(Class* klass) {
188    DCHECK(klass != NULL);
189    DCHECK(GetClass<kVerifyNone>() != NULL);
190    return klass->IsAssignableFrom(GetClass<kVerifyFlags>());
191  }
192  
193  template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
IsClass()194  inline 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  
201  template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
AsClass()202  inline Class* Object::AsClass() {
203    DCHECK((IsClass<kVerifyFlags, kReadBarrierOption>()));
204    return down_cast<Class*>(this);
205  }
206  
207  template<VerifyObjectFlags kVerifyFlags>
IsObjectArray()208  inline 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  
214  template<class T, VerifyObjectFlags kVerifyFlags>
AsObjectArray()215  inline ObjectArray<T>* Object::AsObjectArray() {
216    DCHECK(IsObjectArray<kVerifyFlags>());
217    return down_cast<ObjectArray<T>*>(this);
218  }
219  
220  template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
IsArrayInstance()221  inline bool Object::IsArrayInstance() {
222    return GetClass<kVerifyFlags, kReadBarrierOption>()->
223        template IsArrayClass<kVerifyFlags, kReadBarrierOption>();
224  }
225  
226  template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
IsArtField()227  inline bool Object::IsArtField() {
228    return GetClass<kVerifyFlags, kReadBarrierOption>()->
229        template IsArtFieldClass<kReadBarrierOption>();
230  }
231  
232  template<VerifyObjectFlags kVerifyFlags>
AsArtField()233  inline ArtField* Object::AsArtField() {
234    DCHECK(IsArtField<kVerifyFlags>());
235    return down_cast<ArtField*>(this);
236  }
237  
238  template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
IsArtMethod()239  inline bool Object::IsArtMethod() {
240    return GetClass<kVerifyFlags, kReadBarrierOption>()->
241        template IsArtMethodClass<kReadBarrierOption>();
242  }
243  
244  template<VerifyObjectFlags kVerifyFlags>
AsArtMethod()245  inline ArtMethod* Object::AsArtMethod() {
246    DCHECK(IsArtMethod<kVerifyFlags>());
247    return down_cast<ArtMethod*>(this);
248  }
249  
250  template<VerifyObjectFlags kVerifyFlags>
IsReferenceInstance()251  inline bool Object::IsReferenceInstance() {
252    return GetClass<kVerifyFlags>()->IsTypeOfReferenceClass();
253  }
254  
255  template<VerifyObjectFlags kVerifyFlags>
AsReference()256  inline Reference* Object::AsReference() {
257    DCHECK(IsReferenceInstance<kVerifyFlags>());
258    return down_cast<Reference*>(this);
259  }
260  
261  template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
AsArray()262  inline Array* Object::AsArray() {
263    DCHECK((IsArrayInstance<kVerifyFlags, kReadBarrierOption>()));
264    return down_cast<Array*>(this);
265  }
266  
267  template<VerifyObjectFlags kVerifyFlags>
AsBooleanArray()268  inline 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  
275  template<VerifyObjectFlags kVerifyFlags>
AsByteArray()276  inline 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  
283  template<VerifyObjectFlags kVerifyFlags>
AsByteSizedArray()284  inline 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  
292  template<VerifyObjectFlags kVerifyFlags>
AsCharArray()293  inline 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  
300  template<VerifyObjectFlags kVerifyFlags>
AsShortArray()301  inline 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  
308  template<VerifyObjectFlags kVerifyFlags>
AsShortSizedArray()309  inline 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  
317  template<VerifyObjectFlags kVerifyFlags>
AsIntArray()318  inline 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  
326  template<VerifyObjectFlags kVerifyFlags>
AsLongArray()327  inline 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  
335  template<VerifyObjectFlags kVerifyFlags>
AsFloatArray()336  inline 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  
343  template<VerifyObjectFlags kVerifyFlags>
AsDoubleArray()344  inline 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  
351  template<VerifyObjectFlags kVerifyFlags>
AsString()352  inline String* Object::AsString() {
353    DCHECK(GetClass<kVerifyFlags>()->IsStringClass());
354    return down_cast<String*>(this);
355  }
356  
357  template<VerifyObjectFlags kVerifyFlags>
AsThrowable()358  inline Throwable* Object::AsThrowable() {
359    DCHECK(GetClass<kVerifyFlags>()->IsThrowableClass());
360    return down_cast<Throwable*>(this);
361  }
362  
363  template<VerifyObjectFlags kVerifyFlags>
IsWeakReferenceInstance()364  inline bool Object::IsWeakReferenceInstance() {
365    return GetClass<kVerifyFlags>()->IsWeakReferenceClass();
366  }
367  
368  template<VerifyObjectFlags kVerifyFlags>
IsSoftReferenceInstance()369  inline bool Object::IsSoftReferenceInstance() {
370    return GetClass<kVerifyFlags>()->IsSoftReferenceClass();
371  }
372  
373  template<VerifyObjectFlags kVerifyFlags>
IsFinalizerReferenceInstance()374  inline bool Object::IsFinalizerReferenceInstance() {
375    return GetClass<kVerifyFlags>()->IsFinalizerReferenceClass();
376  }
377  
378  template<VerifyObjectFlags kVerifyFlags>
AsFinalizerReference()379  inline FinalizerReference* Object::AsFinalizerReference() {
380    DCHECK(IsFinalizerReferenceInstance<kVerifyFlags>());
381    return down_cast<FinalizerReference*>(this);
382  }
383  
384  template<VerifyObjectFlags kVerifyFlags>
IsPhantomReferenceInstance()385  inline bool Object::IsPhantomReferenceInstance() {
386    return GetClass<kVerifyFlags>()->IsPhantomReferenceClass();
387  }
388  
389  template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
SizeOf()390  inline 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  
410  template<VerifyObjectFlags kVerifyFlags, bool kIsVolatile>
GetField32(MemberOffset field_offset)411  inline 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  
424  template<VerifyObjectFlags kVerifyFlags>
GetField32Volatile(MemberOffset field_offset)425  inline int32_t Object::GetField32Volatile(MemberOffset field_offset) {
426    return GetField32<kVerifyFlags, true>(field_offset);
427  }
428  
429  template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags,
430      bool kIsVolatile>
SetField32(MemberOffset field_offset,int32_t new_value)431  inline 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  
452  template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
SetField32Volatile(MemberOffset field_offset,int32_t new_value)453  inline 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  
459  template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
CasFieldWeakSequentiallyConsistent32(MemberOffset field_offset,int32_t old_value,int32_t new_value)460  inline 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  
477  template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
CasFieldWeakRelaxed32(MemberOffset field_offset,int32_t old_value,int32_t new_value)478  inline 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  
495  template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
CasFieldStrongSequentiallyConsistent32(MemberOffset field_offset,int32_t old_value,int32_t new_value)496  inline 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  
513  template<VerifyObjectFlags kVerifyFlags, bool kIsVolatile>
GetField64(MemberOffset field_offset)514  inline 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  
527  template<VerifyObjectFlags kVerifyFlags>
GetField64Volatile(MemberOffset field_offset)528  inline int64_t Object::GetField64Volatile(MemberOffset field_offset) {
529    return GetField64<kVerifyFlags, true>(field_offset);
530  }
531  
532  template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags,
533      bool kIsVolatile>
SetField64(MemberOffset field_offset,int64_t new_value)534  inline 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  
555  template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
SetField64Volatile(MemberOffset field_offset,int64_t new_value)556  inline void Object::SetField64Volatile(MemberOffset field_offset, int64_t new_value) {
557    return SetField64<kTransactionActive, kCheckTransaction, kVerifyFlags, true>(field_offset,
558                                                                                 new_value);
559  }
560  
561  template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
CasFieldWeakSequentiallyConsistent64(MemberOffset field_offset,int64_t old_value,int64_t new_value)562  inline 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  
578  template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
CasFieldStrongSequentiallyConsistent64(MemberOffset field_offset,int64_t old_value,int64_t new_value)579  inline 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  
595  template<class T, VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption,
596           bool kIsVolatile>
GetFieldObject(MemberOffset field_offset)597  inline 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  
614  template<class T, VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
GetFieldObjectVolatile(MemberOffset field_offset)615  inline T* Object::GetFieldObjectVolatile(MemberOffset field_offset) {
616    return GetFieldObject<T, kVerifyFlags, kReadBarrierOption, true>(field_offset);
617  }
618  
619  template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags,
620      bool kIsVolatile>
SetFieldObjectWithoutWriteBarrier(MemberOffset field_offset,Object * new_value)621  inline 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  
654  template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags,
655      bool kIsVolatile>
SetFieldObject(MemberOffset field_offset,Object * new_value)656  inline 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  
666  template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
SetFieldObjectVolatile(MemberOffset field_offset,Object * new_value)667  inline void Object::SetFieldObjectVolatile(MemberOffset field_offset, Object* new_value) {
668    SetFieldObject<kTransactionActive, kCheckTransaction, kVerifyFlags, true>(field_offset,
669                                                                              new_value);
670  }
671  
672  template <VerifyObjectFlags kVerifyFlags>
GetFieldObjectReferenceAddr(MemberOffset field_offset)673  inline 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  
681  template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
CasFieldWeakSequentiallyConsistentObject(MemberOffset field_offset,Object * old_value,Object * new_value)682  inline 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  
713  template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
CasFieldStrongSequentiallyConsistentObject(MemberOffset field_offset,Object * old_value,Object * new_value)714  inline 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  
745  template<bool kVisitClass, bool kIsStatic, typename Visitor>
VisitFieldsReferences(uint32_t ref_offsets,const Visitor & visitor)746  inline 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  
780  template<bool kVisitClass, typename Visitor>
VisitInstanceFieldsReferences(mirror::Class * klass,const Visitor & visitor)781  inline void Object::VisitInstanceFieldsReferences(mirror::Class* klass, const Visitor& visitor) {
782    VisitFieldsReferences<kVisitClass, false>(
783        klass->GetReferenceInstanceOffsets<kVerifyNone>(), visitor);
784  }
785  
786  template<bool kVisitClass, typename Visitor>
VisitStaticFieldsReferences(mirror::Class * klass,const Visitor & visitor)787  inline 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  
793  template <const bool kVisitClass, VerifyObjectFlags kVerifyFlags, typename Visitor,
794      typename JavaLangRefVisitor>
VisitReferences(const Visitor & visitor,const JavaLangRefVisitor & ref_visitor)795  inline 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