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 "array-inl.h"
23 #include "art_field.h"
24 #include "art_method.h"
25 #include "base/atomic.h"
26 #include "class-inl.h"
27 #include "class_flags.h"
28 #include "class_linker.h"
29 #include "dex_cache.h"
30 #include "heap_poisoning.h"
31 #include "lock_word-inl.h"
32 #include "monitor.h"
33 #include "obj_ptr-inl.h"
34 #include "object-readbarrier-inl.h"
35 #include "object_array-inl.h"
36 #include "object_reference-inl.h"
37 #include "read_barrier-inl.h"
38 #include "reference.h"
39 #include "runtime.h"
40 #include "string-inl.h"
41 #include "throwable.h"
42 
43 namespace art {
44 namespace mirror {
45 
ClassSize(PointerSize pointer_size)46 inline uint32_t Object::ClassSize(PointerSize pointer_size) {
47   uint32_t vtable_entries = kVTableLength;
48   return Class::ComputeClassSize(true, vtable_entries, 0, 0, 0, 0, 0, pointer_size);
49 }
50 
51 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
GetClass()52 inline Class* Object::GetClass() {
53   return GetFieldObject<Class, kVerifyFlags, kReadBarrierOption>(
54       OFFSET_OF_OBJECT_MEMBER(Object, klass_));
55 }
56 
57 template<VerifyObjectFlags kVerifyFlags>
SetClass(ObjPtr<Class> new_klass)58 inline void Object::SetClass(ObjPtr<Class> new_klass) {
59   // new_klass may be null prior to class linker initialization.
60   // We don't mark the card as this occurs as part of object allocation. Not all objects have
61   // backing cards, such as large objects.
62   // We use non transactional version since we can't undo this write. We also disable checking as
63   // we may run in transaction mode here.
64   SetFieldObjectWithoutWriteBarrier<false, false,
65       static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis)>(
66       OFFSET_OF_OBJECT_MEMBER(Object, klass_), new_klass);
67 }
68 
69 template<VerifyObjectFlags kVerifyFlags>
SetLockWord(LockWord new_val,bool as_volatile)70 inline void Object::SetLockWord(LockWord new_val, bool as_volatile) {
71   // Force use of non-transactional mode and do not check.
72   if (as_volatile) {
73     SetField32Volatile<false, false, kVerifyFlags>(
74         OFFSET_OF_OBJECT_MEMBER(Object, monitor_), new_val.GetValue());
75   } else {
76     SetField32<false, false, kVerifyFlags>(
77         OFFSET_OF_OBJECT_MEMBER(Object, monitor_), new_val.GetValue());
78   }
79 }
80 
CasLockWordWeakSequentiallyConsistent(LockWord old_val,LockWord new_val)81 inline bool Object::CasLockWordWeakSequentiallyConsistent(LockWord old_val, LockWord new_val) {
82   // Force use of non-transactional mode and do not check.
83   return CasFieldWeakSequentiallyConsistent32<false, false>(
84       OFFSET_OF_OBJECT_MEMBER(Object, monitor_), old_val.GetValue(), new_val.GetValue());
85 }
86 
CasLockWordWeakAcquire(LockWord old_val,LockWord new_val)87 inline bool Object::CasLockWordWeakAcquire(LockWord old_val, LockWord new_val) {
88   // Force use of non-transactional mode and do not check.
89   return CasFieldWeakAcquire32<false, false>(
90       OFFSET_OF_OBJECT_MEMBER(Object, monitor_), old_val.GetValue(), new_val.GetValue());
91 }
92 
GetLockOwnerThreadId()93 inline uint32_t Object::GetLockOwnerThreadId() {
94   return Monitor::GetLockOwnerThreadId(this);
95 }
96 
MonitorEnter(Thread * self)97 inline mirror::Object* Object::MonitorEnter(Thread* self) {
98   return Monitor::MonitorEnter(self, this, /*trylock*/false);
99 }
100 
MonitorTryEnter(Thread * self)101 inline mirror::Object* Object::MonitorTryEnter(Thread* self) {
102   return Monitor::MonitorEnter(self, this, /*trylock*/true);
103 }
104 
MonitorExit(Thread * self)105 inline bool Object::MonitorExit(Thread* self) {
106   return Monitor::MonitorExit(self, this);
107 }
108 
Notify(Thread * self)109 inline void Object::Notify(Thread* self) {
110   Monitor::Notify(self, this);
111 }
112 
NotifyAll(Thread * self)113 inline void Object::NotifyAll(Thread* self) {
114   Monitor::NotifyAll(self, this);
115 }
116 
Wait(Thread * self)117 inline void Object::Wait(Thread* self) {
118   Monitor::Wait(self, this, 0, 0, true, kWaiting);
119 }
120 
Wait(Thread * self,int64_t ms,int32_t ns)121 inline void Object::Wait(Thread* self, int64_t ms, int32_t ns) {
122   Monitor::Wait(self, this, ms, ns, true, kTimedWaiting);
123 }
124 
GetMarkBit()125 inline uint32_t Object::GetMarkBit() {
126 #ifdef USE_READ_BARRIER
127   return GetLockWord(false).MarkBitState();
128 #else
129   LOG(FATAL) << "Unreachable";
130   UNREACHABLE();
131 #endif
132 }
133 
SetReadBarrierState(uint32_t rb_state)134 inline void Object::SetReadBarrierState(uint32_t rb_state) {
135   if (!kUseBakerReadBarrier) {
136     LOG(FATAL) << "Unreachable";
137     UNREACHABLE();
138   }
139   DCHECK(ReadBarrier::IsValidReadBarrierState(rb_state)) << rb_state;
140   LockWord lw = GetLockWord(false);
141   lw.SetReadBarrierState(rb_state);
142   SetLockWord(lw, false);
143 }
144 
AssertReadBarrierState()145 inline void Object::AssertReadBarrierState() const {
146   CHECK(kUseBakerReadBarrier);
147   Object* obj = const_cast<Object*>(this);
148   DCHECK(obj->GetReadBarrierState() == ReadBarrier::WhiteState())
149       << "Bad Baker pointer: obj=" << reinterpret_cast<void*>(obj)
150       << " rb_state" << reinterpret_cast<void*>(obj->GetReadBarrierState());
151 }
152 
153 template<VerifyObjectFlags kVerifyFlags>
VerifierInstanceOf(ObjPtr<Class> klass)154 inline bool Object::VerifierInstanceOf(ObjPtr<Class> klass) {
155   DCHECK(klass != nullptr);
156   DCHECK(GetClass<kVerifyFlags>() != nullptr);
157   return klass->IsInterface() || InstanceOf(klass);
158 }
159 
160 template<VerifyObjectFlags kVerifyFlags>
InstanceOf(ObjPtr<Class> klass)161 inline bool Object::InstanceOf(ObjPtr<Class> klass) {
162   DCHECK(klass != nullptr);
163   DCHECK(GetClass<kVerifyNone>() != nullptr)
164       << "this=" << std::hex << reinterpret_cast<uintptr_t>(this) << std::dec;
165   return klass->IsAssignableFrom(GetClass<kVerifyFlags>());
166 }
167 
168 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
IsClass()169 inline bool Object::IsClass() {
170   Class* java_lang_Class = GetClass<kVerifyFlags, kReadBarrierOption>()->
171       template GetClass<kVerifyFlags, kReadBarrierOption>();
172   return GetClass<static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis),
173       kReadBarrierOption>() == java_lang_Class;
174 }
175 
176 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
AsClass()177 inline Class* Object::AsClass() {
178   DCHECK((IsClass<kVerifyFlags, kReadBarrierOption>()));
179   return down_cast<Class*>(this);
180 }
181 
182 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
IsObjectArray()183 inline bool Object::IsObjectArray() {
184   constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
185   return IsArrayInstance<kVerifyFlags, kReadBarrierOption>() &&
186       !GetClass<kNewFlags, kReadBarrierOption>()->
187           template GetComponentType<kNewFlags, kReadBarrierOption>()->IsPrimitive();
188 }
189 
190 template<class T, VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
AsObjectArray()191 inline ObjectArray<T>* Object::AsObjectArray() {
192   DCHECK((IsObjectArray<kVerifyFlags, kReadBarrierOption>()));
193   return down_cast<ObjectArray<T>*>(this);
194 }
195 
196 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
IsArrayInstance()197 inline bool Object::IsArrayInstance() {
198   return GetClass<kVerifyFlags, kReadBarrierOption>()->
199       template IsArrayClass<kVerifyFlags, kReadBarrierOption>();
200 }
201 
202 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
IsReferenceInstance()203 inline bool Object::IsReferenceInstance() {
204   return GetClass<kVerifyFlags, kReadBarrierOption>()->IsTypeOfReferenceClass();
205 }
206 
207 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
AsReference()208 inline Reference* Object::AsReference() {
209   DCHECK((IsReferenceInstance<kVerifyFlags, kReadBarrierOption>()));
210   return down_cast<Reference*>(this);
211 }
212 
213 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
AsArray()214 inline Array* Object::AsArray() {
215   DCHECK((IsArrayInstance<kVerifyFlags, kReadBarrierOption>()));
216   return down_cast<Array*>(this);
217 }
218 
219 template<VerifyObjectFlags kVerifyFlags>
AsBooleanArray()220 inline BooleanArray* Object::AsBooleanArray() {
221   constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
222   DCHECK(GetClass<kVerifyFlags>()->IsArrayClass());
223   DCHECK(GetClass<kNewFlags>()->GetComponentType()->IsPrimitiveBoolean());
224   return down_cast<BooleanArray*>(this);
225 }
226 
227 template<VerifyObjectFlags kVerifyFlags>
AsByteArray()228 inline ByteArray* Object::AsByteArray() {
229   constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
230   DCHECK(GetClass<kVerifyFlags>()->IsArrayClass());
231   DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveByte());
232   return down_cast<ByteArray*>(this);
233 }
234 
235 template<VerifyObjectFlags kVerifyFlags>
AsByteSizedArray()236 inline ByteArray* Object::AsByteSizedArray() {
237   constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
238   DCHECK(GetClass<kVerifyFlags>()->IsArrayClass());
239   DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveByte() ||
240          GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveBoolean());
241   return down_cast<ByteArray*>(this);
242 }
243 
244 template<VerifyObjectFlags kVerifyFlags>
AsCharArray()245 inline CharArray* Object::AsCharArray() {
246   constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
247   DCHECK(GetClass<kVerifyFlags>()->IsArrayClass());
248   DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveChar());
249   return down_cast<CharArray*>(this);
250 }
251 
252 template<VerifyObjectFlags kVerifyFlags>
AsShortArray()253 inline ShortArray* Object::AsShortArray() {
254   constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
255   DCHECK(GetClass<kVerifyFlags>()->IsArrayClass());
256   DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveShort());
257   return down_cast<ShortArray*>(this);
258 }
259 
260 template<VerifyObjectFlags kVerifyFlags>
AsShortSizedArray()261 inline ShortArray* Object::AsShortSizedArray() {
262   constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
263   DCHECK(GetClass<kVerifyFlags>()->IsArrayClass());
264   DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveShort() ||
265          GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveChar());
266   return down_cast<ShortArray*>(this);
267 }
268 
269 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
IsIntArray()270 inline bool Object::IsIntArray() {
271   constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
272   ObjPtr<Class> klass = GetClass<kVerifyFlags, kReadBarrierOption>();
273   ObjPtr<Class> component_type = klass->GetComponentType<kVerifyFlags, kReadBarrierOption>();
274   return component_type != nullptr && component_type->template IsPrimitiveInt<kNewFlags>();
275 }
276 
277 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
AsIntArray()278 inline IntArray* Object::AsIntArray() {
279   DCHECK((IsIntArray<kVerifyFlags, kReadBarrierOption>()));
280   return down_cast<IntArray*>(this);
281 }
282 
283 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
IsLongArray()284 inline bool Object::IsLongArray() {
285   constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
286   ObjPtr<Class> klass = GetClass<kVerifyFlags, kReadBarrierOption>();
287   ObjPtr<Class> component_type = klass->GetComponentType<kVerifyFlags, kReadBarrierOption>();
288   return component_type != nullptr && component_type->template IsPrimitiveLong<kNewFlags>();
289 }
290 
291 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
AsLongArray()292 inline LongArray* Object::AsLongArray() {
293   DCHECK((IsLongArray<kVerifyFlags, kReadBarrierOption>()));
294   return down_cast<LongArray*>(this);
295 }
296 
297 template<VerifyObjectFlags kVerifyFlags>
IsFloatArray()298 inline bool Object::IsFloatArray() {
299   constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
300   auto* component_type = GetClass<kVerifyFlags>()->GetComponentType();
301   return component_type != nullptr && component_type->template IsPrimitiveFloat<kNewFlags>();
302 }
303 
304 template<VerifyObjectFlags kVerifyFlags>
AsFloatArray()305 inline FloatArray* Object::AsFloatArray() {
306   DCHECK(IsFloatArray<kVerifyFlags>());
307   constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
308   DCHECK(GetClass<kVerifyFlags>()->IsArrayClass());
309   DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveFloat());
310   return down_cast<FloatArray*>(this);
311 }
312 
313 template<VerifyObjectFlags kVerifyFlags>
IsDoubleArray()314 inline bool Object::IsDoubleArray() {
315   constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
316   auto* component_type = GetClass<kVerifyFlags>()->GetComponentType();
317   return component_type != nullptr && component_type->template IsPrimitiveDouble<kNewFlags>();
318 }
319 
320 template<VerifyObjectFlags kVerifyFlags>
AsDoubleArray()321 inline DoubleArray* Object::AsDoubleArray() {
322   DCHECK(IsDoubleArray<kVerifyFlags>());
323   constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
324   DCHECK(GetClass<kVerifyFlags>()->IsArrayClass());
325   DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveDouble());
326   return down_cast<DoubleArray*>(this);
327 }
328 
329 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
IsString()330 inline bool Object::IsString() {
331   return GetClass<kVerifyFlags, kReadBarrierOption>()->IsStringClass();
332 }
333 
334 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
AsString()335 inline String* Object::AsString() {
336   DCHECK((IsString<kVerifyFlags, kReadBarrierOption>()));
337   return down_cast<String*>(this);
338 }
339 
340 template<VerifyObjectFlags kVerifyFlags>
AsThrowable()341 inline Throwable* Object::AsThrowable() {
342   DCHECK(GetClass<kVerifyFlags>()->IsThrowableClass());
343   return down_cast<Throwable*>(this);
344 }
345 
346 template<VerifyObjectFlags kVerifyFlags>
IsWeakReferenceInstance()347 inline bool Object::IsWeakReferenceInstance() {
348   return GetClass<kVerifyFlags>()->IsWeakReferenceClass();
349 }
350 
351 template<VerifyObjectFlags kVerifyFlags>
IsSoftReferenceInstance()352 inline bool Object::IsSoftReferenceInstance() {
353   return GetClass<kVerifyFlags>()->IsSoftReferenceClass();
354 }
355 
356 template<VerifyObjectFlags kVerifyFlags>
IsFinalizerReferenceInstance()357 inline bool Object::IsFinalizerReferenceInstance() {
358   return GetClass<kVerifyFlags>()->IsFinalizerReferenceClass();
359 }
360 
361 template<VerifyObjectFlags kVerifyFlags>
AsFinalizerReference()362 inline FinalizerReference* Object::AsFinalizerReference() {
363   DCHECK(IsFinalizerReferenceInstance<kVerifyFlags>());
364   return down_cast<FinalizerReference*>(this);
365 }
366 
367 template<VerifyObjectFlags kVerifyFlags>
IsPhantomReferenceInstance()368 inline bool Object::IsPhantomReferenceInstance() {
369   return GetClass<kVerifyFlags>()->IsPhantomReferenceClass();
370 }
371 
372 template<VerifyObjectFlags kVerifyFlags>
SizeOf()373 inline size_t Object::SizeOf() {
374   // Read barrier is never required for SizeOf since objects sizes are constant. Reading from-space
375   // values is OK because of that.
376   static constexpr ReadBarrierOption kReadBarrierOption = kWithoutReadBarrier;
377   size_t result;
378   constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
379   if (IsArrayInstance<kVerifyFlags, kReadBarrierOption>()) {
380     result = AsArray<kNewFlags, kReadBarrierOption>()->
381         template SizeOf<kNewFlags, kReadBarrierOption>();
382   } else if (IsClass<kNewFlags, kReadBarrierOption>()) {
383     result = AsClass<kNewFlags, kReadBarrierOption>()->
384         template SizeOf<kNewFlags, kReadBarrierOption>();
385   } else if (GetClass<kNewFlags, kReadBarrierOption>()->IsStringClass()) {
386     result = AsString<kNewFlags, kReadBarrierOption>()->
387         template SizeOf<kNewFlags>();
388   } else {
389     result = GetClass<kNewFlags, kReadBarrierOption>()->
390         template GetObjectSize<kNewFlags, kReadBarrierOption>();
391   }
392   DCHECK_GE(result, sizeof(Object))
393       << " class=" << Class::PrettyClass(GetClass<kNewFlags, kReadBarrierOption>());
394   return result;
395 }
396 
397 template<VerifyObjectFlags kVerifyFlags, bool kIsVolatile>
GetFieldByte(MemberOffset field_offset)398 inline int8_t Object::GetFieldByte(MemberOffset field_offset) {
399   if (kVerifyFlags & kVerifyThis) {
400     VerifyObject(this);
401   }
402   return GetField<int8_t, kIsVolatile>(field_offset);
403 }
404 
405 template<VerifyObjectFlags kVerifyFlags>
GetFieldBooleanVolatile(MemberOffset field_offset)406 inline uint8_t Object::GetFieldBooleanVolatile(MemberOffset field_offset) {
407   return GetFieldBoolean<kVerifyFlags, true>(field_offset);
408 }
409 
410 template<VerifyObjectFlags kVerifyFlags>
GetFieldByteVolatile(MemberOffset field_offset)411 inline int8_t Object::GetFieldByteVolatile(MemberOffset field_offset) {
412   return GetFieldByte<kVerifyFlags, true>(field_offset);
413 }
414 
415 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags,
416     bool kIsVolatile>
SetFieldBoolean(MemberOffset field_offset,uint8_t new_value)417 inline void Object::SetFieldBoolean(MemberOffset field_offset, uint8_t new_value)
418     REQUIRES_SHARED(Locks::mutator_lock_) {
419   if (kCheckTransaction) {
420     DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
421   }
422   if (kTransactionActive) {
423     Runtime::Current()->RecordWriteFieldBoolean(this, field_offset,
424                                            GetFieldBoolean<kVerifyFlags, kIsVolatile>(field_offset),
425                                            kIsVolatile);
426   }
427   if (kVerifyFlags & kVerifyThis) {
428     VerifyObject(this);
429   }
430   SetField<uint8_t, kIsVolatile>(field_offset, new_value);
431 }
432 
433 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags,
434     bool kIsVolatile>
SetFieldByte(MemberOffset field_offset,int8_t new_value)435 inline void Object::SetFieldByte(MemberOffset field_offset, int8_t new_value)
436     REQUIRES_SHARED(Locks::mutator_lock_) {
437   if (kCheckTransaction) {
438     DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
439   }
440   if (kTransactionActive) {
441     Runtime::Current()->RecordWriteFieldByte(this, field_offset,
442                                            GetFieldByte<kVerifyFlags, kIsVolatile>(field_offset),
443                                            kIsVolatile);
444   }
445   if (kVerifyFlags & kVerifyThis) {
446     VerifyObject(this);
447   }
448   SetField<int8_t, kIsVolatile>(field_offset, new_value);
449 }
450 
451 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
SetFieldBooleanVolatile(MemberOffset field_offset,uint8_t new_value)452 inline void Object::SetFieldBooleanVolatile(MemberOffset field_offset, uint8_t new_value) {
453   return SetFieldBoolean<kTransactionActive, kCheckTransaction, kVerifyFlags, true>(
454       field_offset, new_value);
455 }
456 
457 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
SetFieldByteVolatile(MemberOffset field_offset,int8_t new_value)458 inline void Object::SetFieldByteVolatile(MemberOffset field_offset, int8_t new_value) {
459   return SetFieldByte<kTransactionActive, kCheckTransaction, kVerifyFlags, true>(
460       field_offset, new_value);
461 }
462 
463 template<VerifyObjectFlags kVerifyFlags, bool kIsVolatile>
GetFieldChar(MemberOffset field_offset)464 inline uint16_t Object::GetFieldChar(MemberOffset field_offset) {
465   if (kVerifyFlags & kVerifyThis) {
466     VerifyObject(this);
467   }
468   return GetField<uint16_t, kIsVolatile>(field_offset);
469 }
470 
471 template<VerifyObjectFlags kVerifyFlags, bool kIsVolatile>
GetFieldShort(MemberOffset field_offset)472 inline int16_t Object::GetFieldShort(MemberOffset field_offset) {
473   if (kVerifyFlags & kVerifyThis) {
474     VerifyObject(this);
475   }
476   return GetField<int16_t, kIsVolatile>(field_offset);
477 }
478 
479 template<VerifyObjectFlags kVerifyFlags>
GetFieldCharVolatile(MemberOffset field_offset)480 inline uint16_t Object::GetFieldCharVolatile(MemberOffset field_offset) {
481   return GetFieldChar<kVerifyFlags, true>(field_offset);
482 }
483 
484 template<VerifyObjectFlags kVerifyFlags>
GetFieldShortVolatile(MemberOffset field_offset)485 inline int16_t Object::GetFieldShortVolatile(MemberOffset field_offset) {
486   return GetFieldShort<kVerifyFlags, true>(field_offset);
487 }
488 
489 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags,
490     bool kIsVolatile>
SetFieldChar(MemberOffset field_offset,uint16_t new_value)491 inline void Object::SetFieldChar(MemberOffset field_offset, uint16_t new_value) {
492   if (kCheckTransaction) {
493     DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
494   }
495   if (kTransactionActive) {
496     Runtime::Current()->RecordWriteFieldChar(this, field_offset,
497                                            GetFieldChar<kVerifyFlags, kIsVolatile>(field_offset),
498                                            kIsVolatile);
499   }
500   if (kVerifyFlags & kVerifyThis) {
501     VerifyObject(this);
502   }
503   SetField<uint16_t, kIsVolatile>(field_offset, new_value);
504 }
505 
506 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags,
507     bool kIsVolatile>
SetFieldShort(MemberOffset field_offset,int16_t new_value)508 inline void Object::SetFieldShort(MemberOffset field_offset, int16_t new_value) {
509   if (kCheckTransaction) {
510     DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
511   }
512   if (kTransactionActive) {
513     Runtime::Current()->RecordWriteFieldChar(this, field_offset,
514                                            GetFieldShort<kVerifyFlags, kIsVolatile>(field_offset),
515                                            kIsVolatile);
516   }
517   if (kVerifyFlags & kVerifyThis) {
518     VerifyObject(this);
519   }
520   SetField<int16_t, kIsVolatile>(field_offset, new_value);
521 }
522 
523 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
SetFieldCharVolatile(MemberOffset field_offset,uint16_t new_value)524 inline void Object::SetFieldCharVolatile(MemberOffset field_offset, uint16_t new_value) {
525   return SetFieldChar<kTransactionActive, kCheckTransaction, kVerifyFlags, true>(
526       field_offset, new_value);
527 }
528 
529 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
SetFieldShortVolatile(MemberOffset field_offset,int16_t new_value)530 inline void Object::SetFieldShortVolatile(MemberOffset field_offset, int16_t new_value) {
531   return SetFieldShort<kTransactionActive, kCheckTransaction, kVerifyFlags, true>(
532       field_offset, new_value);
533 }
534 
535 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags,
536     bool kIsVolatile>
SetField32(MemberOffset field_offset,int32_t new_value)537 inline void Object::SetField32(MemberOffset field_offset, int32_t new_value) {
538   if (kCheckTransaction) {
539     DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
540   }
541   if (kTransactionActive) {
542     Runtime::Current()->RecordWriteField32(this, field_offset,
543                                            GetField32<kVerifyFlags, kIsVolatile>(field_offset),
544                                            kIsVolatile);
545   }
546   if (kVerifyFlags & kVerifyThis) {
547     VerifyObject(this);
548   }
549   SetField<int32_t, kIsVolatile>(field_offset, new_value);
550 }
551 
552 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
SetField32Volatile(MemberOffset field_offset,int32_t new_value)553 inline void Object::SetField32Volatile(MemberOffset field_offset, int32_t new_value) {
554   SetField32<kTransactionActive, kCheckTransaction, kVerifyFlags, true>(field_offset, new_value);
555 }
556 
557 template<bool kCheckTransaction, VerifyObjectFlags kVerifyFlags, bool kIsVolatile>
SetField32Transaction(MemberOffset field_offset,int32_t new_value)558 inline void Object::SetField32Transaction(MemberOffset field_offset, int32_t new_value) {
559   if (Runtime::Current()->IsActiveTransaction()) {
560     SetField32<true, kCheckTransaction, kVerifyFlags, kIsVolatile>(field_offset, new_value);
561   } else {
562     SetField32<false, kCheckTransaction, kVerifyFlags, kIsVolatile>(field_offset, new_value);
563   }
564 }
565 
566 // TODO: Pass memory_order_ and strong/weak as arguments to avoid code duplication?
567 
568 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
CasFieldWeakSequentiallyConsistent32(MemberOffset field_offset,int32_t old_value,int32_t new_value)569 inline bool Object::CasFieldWeakSequentiallyConsistent32(MemberOffset field_offset,
570                                                          int32_t old_value, int32_t new_value) {
571   if (kCheckTransaction) {
572     DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
573   }
574   if (kTransactionActive) {
575     Runtime::Current()->RecordWriteField32(this, field_offset, old_value, true);
576   }
577   if (kVerifyFlags & kVerifyThis) {
578     VerifyObject(this);
579   }
580   uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
581   AtomicInteger* atomic_addr = reinterpret_cast<AtomicInteger*>(raw_addr);
582 
583   return atomic_addr->CompareAndSetWeakSequentiallyConsistent(old_value, new_value);
584 }
585 
586 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
CasFieldWeakAcquire32(MemberOffset field_offset,int32_t old_value,int32_t new_value)587 inline bool Object::CasFieldWeakAcquire32(MemberOffset field_offset,
588                                           int32_t old_value, int32_t new_value) {
589   if (kCheckTransaction) {
590     DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
591   }
592   if (kTransactionActive) {
593     Runtime::Current()->RecordWriteField32(this, field_offset, old_value, true);
594   }
595   if (kVerifyFlags & kVerifyThis) {
596     VerifyObject(this);
597   }
598   uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
599   AtomicInteger* atomic_addr = reinterpret_cast<AtomicInteger*>(raw_addr);
600 
601   return atomic_addr->CompareAndSetWeakAcquire(old_value, new_value);
602 }
603 
604 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
CasFieldWeakRelease32(MemberOffset field_offset,int32_t old_value,int32_t new_value)605 inline bool Object::CasFieldWeakRelease32(MemberOffset field_offset,
606                                           int32_t old_value, int32_t new_value) {
607   if (kCheckTransaction) {
608     DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
609   }
610   if (kTransactionActive) {
611     Runtime::Current()->RecordWriteField32(this, field_offset, old_value, true);
612   }
613   if (kVerifyFlags & kVerifyThis) {
614     VerifyObject(this);
615   }
616   uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
617   AtomicInteger* atomic_addr = reinterpret_cast<AtomicInteger*>(raw_addr);
618 
619   return atomic_addr->CompareAndSetWeakRelease(old_value, new_value);
620 }
621 
622 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
CasFieldStrongSequentiallyConsistent32(MemberOffset field_offset,int32_t old_value,int32_t new_value)623 inline bool Object::CasFieldStrongSequentiallyConsistent32(MemberOffset field_offset,
624                                                            int32_t old_value, int32_t new_value) {
625   if (kCheckTransaction) {
626     DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
627   }
628   if (kTransactionActive) {
629     Runtime::Current()->RecordWriteField32(this, field_offset, old_value, true);
630   }
631   if (kVerifyFlags & kVerifyThis) {
632     VerifyObject(this);
633   }
634   uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
635   AtomicInteger* atomic_addr = reinterpret_cast<AtomicInteger*>(raw_addr);
636 
637   return atomic_addr->CompareAndSetStrongSequentiallyConsistent(old_value, new_value);
638 }
639 
640 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags,
641     bool kIsVolatile>
SetField64(MemberOffset field_offset,int64_t new_value)642 inline void Object::SetField64(MemberOffset field_offset, int64_t new_value) {
643   if (kCheckTransaction) {
644     DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
645   }
646   if (kTransactionActive) {
647     Runtime::Current()->RecordWriteField64(this, field_offset,
648                                            GetField64<kVerifyFlags, kIsVolatile>(field_offset),
649                                            kIsVolatile);
650   }
651   if (kVerifyFlags & kVerifyThis) {
652     VerifyObject(this);
653   }
654   SetField<int64_t, kIsVolatile>(field_offset, new_value);
655 }
656 
657 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
SetField64Volatile(MemberOffset field_offset,int64_t new_value)658 inline void Object::SetField64Volatile(MemberOffset field_offset, int64_t new_value) {
659   return SetField64<kTransactionActive, kCheckTransaction, kVerifyFlags, true>(field_offset,
660                                                                                new_value);
661 }
662 
663 template<bool kCheckTransaction, VerifyObjectFlags kVerifyFlags, bool kIsVolatile>
SetField64Transaction(MemberOffset field_offset,int32_t new_value)664 inline void Object::SetField64Transaction(MemberOffset field_offset, int32_t new_value) {
665   if (Runtime::Current()->IsActiveTransaction()) {
666     SetField64<true, kCheckTransaction, kVerifyFlags, kIsVolatile>(field_offset, new_value);
667   } else {
668     SetField64<false, kCheckTransaction, kVerifyFlags, kIsVolatile>(field_offset, new_value);
669   }
670 }
671 
672 template<typename kSize>
GetFieldAcquire(MemberOffset field_offset)673 inline kSize Object::GetFieldAcquire(MemberOffset field_offset) {
674   const uint8_t* raw_addr = reinterpret_cast<const uint8_t*>(this) + field_offset.Int32Value();
675   const kSize* addr = reinterpret_cast<const kSize*>(raw_addr);
676   return reinterpret_cast<const Atomic<kSize>*>(addr)->LoadAcquire();
677 }
678 
679 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
CasFieldWeakSequentiallyConsistent64(MemberOffset field_offset,int64_t old_value,int64_t new_value)680 inline bool Object::CasFieldWeakSequentiallyConsistent64(MemberOffset field_offset,
681                                                          int64_t old_value, int64_t new_value) {
682   if (kCheckTransaction) {
683     DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
684   }
685   if (kTransactionActive) {
686     Runtime::Current()->RecordWriteField64(this, field_offset, old_value, true);
687   }
688   if (kVerifyFlags & kVerifyThis) {
689     VerifyObject(this);
690   }
691   uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
692   Atomic<int64_t>* atomic_addr = reinterpret_cast<Atomic<int64_t>*>(raw_addr);
693   return atomic_addr->CompareAndSetWeakSequentiallyConsistent(old_value, new_value);
694 }
695 
696 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
CasFieldStrongSequentiallyConsistent64(MemberOffset field_offset,int64_t old_value,int64_t new_value)697 inline bool Object::CasFieldStrongSequentiallyConsistent64(MemberOffset field_offset,
698                                                            int64_t old_value, int64_t new_value) {
699   if (kCheckTransaction) {
700     DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
701   }
702   if (kTransactionActive) {
703     Runtime::Current()->RecordWriteField64(this, field_offset, old_value, true);
704   }
705   if (kVerifyFlags & kVerifyThis) {
706     VerifyObject(this);
707   }
708   uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
709   Atomic<int64_t>* atomic_addr = reinterpret_cast<Atomic<int64_t>*>(raw_addr);
710   return atomic_addr->CompareAndSetStrongSequentiallyConsistent(old_value, new_value);
711 }
712 
713 template<class T, VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption,
714          bool kIsVolatile>
GetFieldObject(MemberOffset field_offset)715 inline T* Object::GetFieldObject(MemberOffset field_offset) {
716   if (kVerifyFlags & kVerifyThis) {
717     VerifyObject(this);
718   }
719   uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
720   HeapReference<T>* objref_addr = reinterpret_cast<HeapReference<T>*>(raw_addr);
721   T* result = ReadBarrier::Barrier<T, kIsVolatile, kReadBarrierOption>(
722       this,
723       field_offset,
724       objref_addr);
725   if (kVerifyFlags & kVerifyReads) {
726     VerifyObject(result);
727   }
728   return result;
729 }
730 
731 template<class T, VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
GetFieldObjectVolatile(MemberOffset field_offset)732 inline T* Object::GetFieldObjectVolatile(MemberOffset field_offset) {
733   return GetFieldObject<T, kVerifyFlags, kReadBarrierOption, true>(field_offset);
734 }
735 
736 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags,
737     bool kIsVolatile>
SetFieldObjectWithoutWriteBarrier(MemberOffset field_offset,ObjPtr<Object> new_value)738 inline void Object::SetFieldObjectWithoutWriteBarrier(MemberOffset field_offset,
739                                                       ObjPtr<Object> new_value) {
740   if (kCheckTransaction) {
741     DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
742   }
743   if (kTransactionActive) {
744     ObjPtr<Object> obj;
745     if (kIsVolatile) {
746       obj = GetFieldObjectVolatile<Object>(field_offset);
747     } else {
748       obj = GetFieldObject<Object>(field_offset);
749     }
750     Runtime::Current()->RecordWriteFieldReference(this, field_offset, obj.Ptr(), true);
751   }
752   if (kVerifyFlags & kVerifyThis) {
753     VerifyObject(this);
754   }
755   if (kVerifyFlags & kVerifyWrites) {
756     VerifyObject(new_value);
757   }
758   uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
759   HeapReference<Object>* objref_addr = reinterpret_cast<HeapReference<Object>*>(raw_addr);
760   objref_addr->Assign<kIsVolatile>(new_value.Ptr());
761 }
762 
763 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags,
764     bool kIsVolatile>
SetFieldObject(MemberOffset field_offset,ObjPtr<Object> new_value)765 inline void Object::SetFieldObject(MemberOffset field_offset, ObjPtr<Object> new_value) {
766   SetFieldObjectWithoutWriteBarrier<kTransactionActive, kCheckTransaction, kVerifyFlags,
767       kIsVolatile>(field_offset, new_value);
768   if (new_value != nullptr) {
769     Runtime::Current()->GetHeap()->WriteBarrierField(this, field_offset, new_value);
770     // TODO: Check field assignment could theoretically cause thread suspension, TODO: fix this.
771     CheckFieldAssignment(field_offset, new_value);
772   }
773 }
774 
775 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
SetFieldObjectVolatile(MemberOffset field_offset,ObjPtr<Object> new_value)776 inline void Object::SetFieldObjectVolatile(MemberOffset field_offset, ObjPtr<Object> new_value) {
777   SetFieldObject<kTransactionActive, kCheckTransaction, kVerifyFlags, true>(field_offset,
778                                                                             new_value);
779 }
780 
781 template<bool kCheckTransaction, VerifyObjectFlags kVerifyFlags, bool kIsVolatile>
SetFieldObjectTransaction(MemberOffset field_offset,ObjPtr<Object> new_value)782 inline void Object::SetFieldObjectTransaction(MemberOffset field_offset, ObjPtr<Object> new_value) {
783   if (Runtime::Current()->IsActiveTransaction()) {
784     SetFieldObject<true, kCheckTransaction, kVerifyFlags, kIsVolatile>(field_offset, new_value);
785   } else {
786     SetFieldObject<false, kCheckTransaction, kVerifyFlags, kIsVolatile>(field_offset, new_value);
787   }
788 }
789 
790 template <VerifyObjectFlags kVerifyFlags>
GetFieldObjectReferenceAddr(MemberOffset field_offset)791 inline HeapReference<Object>* Object::GetFieldObjectReferenceAddr(MemberOffset field_offset) {
792   if (kVerifyFlags & kVerifyThis) {
793     VerifyObject(this);
794   }
795   return reinterpret_cast<HeapReference<Object>*>(reinterpret_cast<uint8_t*>(this) +
796       field_offset.Int32Value());
797 }
798 
799 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
CasFieldWeakSequentiallyConsistentObject(MemberOffset field_offset,ObjPtr<Object> old_value,ObjPtr<Object> new_value)800 inline bool Object::CasFieldWeakSequentiallyConsistentObject(MemberOffset field_offset,
801                                                              ObjPtr<Object> old_value,
802                                                              ObjPtr<Object> new_value) {
803   bool success = CasFieldWeakSequentiallyConsistentObjectWithoutWriteBarrier<
804       kTransactionActive, kCheckTransaction, kVerifyFlags>(field_offset, old_value, new_value);
805   if (success) {
806     Runtime::Current()->GetHeap()->WriteBarrierField(this, field_offset, new_value);
807   }
808   return success;
809 }
810 
811 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
CasFieldWeakSequentiallyConsistentObjectWithoutWriteBarrier(MemberOffset field_offset,ObjPtr<Object> old_value,ObjPtr<Object> new_value)812 inline bool Object::CasFieldWeakSequentiallyConsistentObjectWithoutWriteBarrier(
813     MemberOffset field_offset,
814     ObjPtr<Object> old_value,
815     ObjPtr<Object> new_value) {
816   if (kCheckTransaction) {
817     DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
818   }
819   if (kVerifyFlags & kVerifyThis) {
820     VerifyObject(this);
821   }
822   if (kVerifyFlags & kVerifyWrites) {
823     VerifyObject(new_value);
824   }
825   if (kVerifyFlags & kVerifyReads) {
826     VerifyObject(old_value);
827   }
828   if (kTransactionActive) {
829     Runtime::Current()->RecordWriteFieldReference(this, field_offset, old_value, true);
830   }
831   uint32_t old_ref(PtrCompression<kPoisonHeapReferences, Object>::Compress(old_value));
832   uint32_t new_ref(PtrCompression<kPoisonHeapReferences, Object>::Compress(new_value));
833   uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
834   Atomic<uint32_t>* atomic_addr = reinterpret_cast<Atomic<uint32_t>*>(raw_addr);
835 
836   bool success = atomic_addr->CompareAndSetWeakSequentiallyConsistent(old_ref, new_ref);
837   return success;
838 }
839 
840 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
CasFieldStrongSequentiallyConsistentObject(MemberOffset field_offset,ObjPtr<Object> old_value,ObjPtr<Object> new_value)841 inline bool Object::CasFieldStrongSequentiallyConsistentObject(MemberOffset field_offset,
842                                                                ObjPtr<Object> old_value,
843                                                                ObjPtr<Object> new_value) {
844   bool success = CasFieldStrongSequentiallyConsistentObjectWithoutWriteBarrier<
845       kTransactionActive, kCheckTransaction, kVerifyFlags>(field_offset, old_value, new_value);
846   if (success) {
847     Runtime::Current()->GetHeap()->WriteBarrierField(this, field_offset, new_value);
848   }
849   return success;
850 }
851 
852 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
CasFieldStrongSequentiallyConsistentObjectWithoutWriteBarrier(MemberOffset field_offset,ObjPtr<Object> old_value,ObjPtr<Object> new_value)853 inline bool Object::CasFieldStrongSequentiallyConsistentObjectWithoutWriteBarrier(
854     MemberOffset field_offset,
855     ObjPtr<Object> old_value,
856     ObjPtr<Object> new_value) {
857   if (kCheckTransaction) {
858     DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
859   }
860   if (kVerifyFlags & kVerifyThis) {
861     VerifyObject(this);
862   }
863   if (kVerifyFlags & kVerifyWrites) {
864     VerifyObject(new_value);
865   }
866   if (kVerifyFlags & kVerifyReads) {
867     VerifyObject(old_value);
868   }
869   if (kTransactionActive) {
870     Runtime::Current()->RecordWriteFieldReference(this, field_offset, old_value, true);
871   }
872   uint32_t old_ref(PtrCompression<kPoisonHeapReferences, Object>::Compress(old_value));
873   uint32_t new_ref(PtrCompression<kPoisonHeapReferences, Object>::Compress(new_value));
874   uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
875   Atomic<uint32_t>* atomic_addr = reinterpret_cast<Atomic<uint32_t>*>(raw_addr);
876 
877   bool success = atomic_addr->CompareAndSetStrongSequentiallyConsistent(old_ref, new_ref);
878   return success;
879 }
880 
881 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
CasFieldWeakRelaxedObjectWithoutWriteBarrier(MemberOffset field_offset,ObjPtr<Object> old_value,ObjPtr<Object> new_value)882 inline bool Object::CasFieldWeakRelaxedObjectWithoutWriteBarrier(
883     MemberOffset field_offset,
884     ObjPtr<Object> old_value,
885     ObjPtr<Object> new_value) {
886   if (kCheckTransaction) {
887     DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
888   }
889   if (kVerifyFlags & kVerifyThis) {
890     VerifyObject(this);
891   }
892   if (kVerifyFlags & kVerifyWrites) {
893     VerifyObject(new_value);
894   }
895   if (kVerifyFlags & kVerifyReads) {
896     VerifyObject(old_value);
897   }
898   if (kTransactionActive) {
899     Runtime::Current()->RecordWriteFieldReference(this, field_offset, old_value, true);
900   }
901   uint32_t old_ref(PtrCompression<kPoisonHeapReferences, Object>::Compress(old_value));
902   uint32_t new_ref(PtrCompression<kPoisonHeapReferences, Object>::Compress(new_value));
903   uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
904   Atomic<uint32_t>* atomic_addr = reinterpret_cast<Atomic<uint32_t>*>(raw_addr);
905 
906   bool success = atomic_addr->CompareAndSetWeakRelaxed(old_ref, new_ref);
907   return success;
908 }
909 
910 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
CasFieldWeakReleaseObjectWithoutWriteBarrier(MemberOffset field_offset,ObjPtr<Object> old_value,ObjPtr<Object> new_value)911 inline bool Object::CasFieldWeakReleaseObjectWithoutWriteBarrier(
912     MemberOffset field_offset,
913     ObjPtr<Object> old_value,
914     ObjPtr<Object> new_value) {
915   if (kCheckTransaction) {
916     DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
917   }
918   if (kVerifyFlags & kVerifyThis) {
919     VerifyObject(this);
920   }
921   if (kVerifyFlags & kVerifyWrites) {
922     VerifyObject(new_value);
923   }
924   if (kVerifyFlags & kVerifyReads) {
925     VerifyObject(old_value);
926   }
927   if (kTransactionActive) {
928     Runtime::Current()->RecordWriteFieldReference(this, field_offset, old_value, true);
929   }
930   uint32_t old_ref(PtrCompression<kPoisonHeapReferences, Object>::Compress(old_value));
931   uint32_t new_ref(PtrCompression<kPoisonHeapReferences, Object>::Compress(new_value));
932   uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
933   Atomic<uint32_t>* atomic_addr = reinterpret_cast<Atomic<uint32_t>*>(raw_addr);
934 
935   bool success = atomic_addr->CompareAndSetWeakRelease(old_ref, new_ref);
936   return success;
937 }
938 
939 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
CompareAndExchangeFieldObject(MemberOffset field_offset,ObjPtr<Object> old_value,ObjPtr<Object> new_value)940 inline ObjPtr<Object> Object::CompareAndExchangeFieldObject(MemberOffset field_offset,
941                                                             ObjPtr<Object> old_value,
942                                                             ObjPtr<Object> new_value) {
943   if (kCheckTransaction) {
944     DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
945   }
946   if (kVerifyFlags & kVerifyThis) {
947     VerifyObject(this);
948   }
949   if (kVerifyFlags & kVerifyWrites) {
950     VerifyObject(new_value);
951   }
952   if (kVerifyFlags & kVerifyReads) {
953     VerifyObject(old_value);
954   }
955   uint32_t old_ref(PtrCompression<kPoisonHeapReferences, Object>::Compress(old_value));
956   uint32_t new_ref(PtrCompression<kPoisonHeapReferences, Object>::Compress(new_value));
957   uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
958   Atomic<uint32_t>* atomic_addr = reinterpret_cast<Atomic<uint32_t>*>(raw_addr);
959   bool success = atomic_addr->CompareAndExchangeStrongSequentiallyConsistent(&old_ref, new_ref);
960   ObjPtr<Object> witness_value(PtrCompression<kPoisonHeapReferences, Object>::Decompress(old_ref));
961   if (kIsDebugBuild) {
962     // Ensure caller has done read barrier on the reference field so it's in the to-space.
963     ReadBarrier::AssertToSpaceInvariant(witness_value.Ptr());
964   }
965   if (kTransactionActive && success) {
966     Runtime::Current()->RecordWriteFieldReference(this, field_offset, witness_value, true);
967   }
968   if (kVerifyFlags & kVerifyReads) {
969     VerifyObject(witness_value);
970   }
971   return witness_value;
972 }
973 
974 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
ExchangeFieldObject(MemberOffset field_offset,ObjPtr<Object> new_value)975 inline ObjPtr<Object> Object::ExchangeFieldObject(MemberOffset field_offset,
976                                                   ObjPtr<Object> new_value) {
977   if (kCheckTransaction) {
978     DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
979   }
980   if (kVerifyFlags & kVerifyThis) {
981     VerifyObject(this);
982   }
983   if (kVerifyFlags & kVerifyWrites) {
984     VerifyObject(new_value);
985   }
986   uint32_t new_ref(PtrCompression<kPoisonHeapReferences, Object>::Compress(new_value));
987   uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
988   Atomic<uint32_t>* atomic_addr = reinterpret_cast<Atomic<uint32_t>*>(raw_addr);
989   uint32_t old_ref = atomic_addr->ExchangeSequentiallyConsistent(new_ref);
990   ObjPtr<Object> old_value(PtrCompression<kPoisonHeapReferences, Object>::Decompress(old_ref));
991   if (kIsDebugBuild) {
992     // Ensure caller has done read barrier on the reference field so it's in the to-space.
993     ReadBarrier::AssertToSpaceInvariant(old_value.Ptr());
994   }
995   if (kTransactionActive) {
996     Runtime::Current()->RecordWriteFieldReference(this, field_offset, old_value, true);
997   }
998   if (kVerifyFlags & kVerifyReads) {
999     VerifyObject(old_value);
1000   }
1001   return old_value;
1002 }
1003 
1004 template<typename T, VerifyObjectFlags kVerifyFlags>
GetPrimitiveFieldViaAccessor(MemberOffset field_offset,Accessor<T> * accessor)1005 inline void Object::GetPrimitiveFieldViaAccessor(MemberOffset field_offset, Accessor<T>* accessor) {
1006   if (kVerifyFlags & kVerifyThis) {
1007     VerifyObject(this);
1008   }
1009   uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
1010   T* addr = reinterpret_cast<T*>(raw_addr);
1011   accessor->Access(addr);
1012 }
1013 
1014 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
UpdateFieldBooleanViaAccessor(MemberOffset field_offset,Accessor<uint8_t> * accessor)1015 inline void Object::UpdateFieldBooleanViaAccessor(MemberOffset field_offset,
1016                                                   Accessor<uint8_t>* accessor) {
1017   if (kCheckTransaction) {
1018     DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
1019   }
1020   if (kTransactionActive) {
1021     static const bool kIsVolatile = true;
1022     uint8_t old_value = GetFieldBoolean<kVerifyFlags, kIsVolatile>(field_offset);
1023     Runtime::Current()->RecordWriteFieldBoolean(this, field_offset, old_value, kIsVolatile);
1024   }
1025   if (kVerifyFlags & kVerifyThis) {
1026     VerifyObject(this);
1027   }
1028   uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
1029   uint8_t* addr = raw_addr;
1030   accessor->Access(addr);
1031 }
1032 
1033 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
UpdateFieldByteViaAccessor(MemberOffset field_offset,Accessor<int8_t> * accessor)1034 inline void Object::UpdateFieldByteViaAccessor(MemberOffset field_offset,
1035                                                Accessor<int8_t>* accessor) {
1036   if (kCheckTransaction) {
1037     DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
1038   }
1039   if (kTransactionActive) {
1040     static const bool kIsVolatile = true;
1041     int8_t old_value = GetFieldByte<kVerifyFlags, kIsVolatile>(field_offset);
1042     Runtime::Current()->RecordWriteFieldByte(this, field_offset, old_value, kIsVolatile);
1043   }
1044   if (kVerifyFlags & kVerifyThis) {
1045     VerifyObject(this);
1046   }
1047   uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
1048   int8_t* addr = reinterpret_cast<int8_t*>(raw_addr);
1049   accessor->Access(addr);
1050 }
1051 
1052 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
UpdateFieldCharViaAccessor(MemberOffset field_offset,Accessor<uint16_t> * accessor)1053 inline void Object::UpdateFieldCharViaAccessor(MemberOffset field_offset,
1054                                                Accessor<uint16_t>* accessor) {
1055   if (kCheckTransaction) {
1056     DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
1057   }
1058   if (kTransactionActive) {
1059     static const bool kIsVolatile = true;
1060     uint16_t old_value = GetFieldChar<kVerifyFlags, kIsVolatile>(field_offset);
1061     Runtime::Current()->RecordWriteFieldChar(this, field_offset, old_value, kIsVolatile);
1062   }
1063   if (kVerifyFlags & kVerifyThis) {
1064     VerifyObject(this);
1065   }
1066   uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
1067   uint16_t* addr = reinterpret_cast<uint16_t*>(raw_addr);
1068   accessor->Access(addr);
1069 }
1070 
1071 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
UpdateFieldShortViaAccessor(MemberOffset field_offset,Accessor<int16_t> * accessor)1072 inline void Object::UpdateFieldShortViaAccessor(MemberOffset field_offset,
1073                                                 Accessor<int16_t>* accessor) {
1074   if (kCheckTransaction) {
1075     DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
1076   }
1077   if (kTransactionActive) {
1078     static const bool kIsVolatile = true;
1079     int16_t old_value = GetFieldShort<kVerifyFlags, kIsVolatile>(field_offset);
1080     Runtime::Current()->RecordWriteFieldShort(this, field_offset, old_value, kIsVolatile);
1081   }
1082   if (kVerifyFlags & kVerifyThis) {
1083     VerifyObject(this);
1084   }
1085   uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
1086   int16_t* addr = reinterpret_cast<int16_t*>(raw_addr);
1087   accessor->Access(addr);
1088 }
1089 
1090 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
UpdateField32ViaAccessor(MemberOffset field_offset,Accessor<int32_t> * accessor)1091 inline void Object::UpdateField32ViaAccessor(MemberOffset field_offset,
1092                                              Accessor<int32_t>* accessor) {
1093   if (kCheckTransaction) {
1094     DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
1095   }
1096   if (kTransactionActive) {
1097     static const bool kIsVolatile = true;
1098     int32_t old_value = GetField32<kVerifyFlags, kIsVolatile>(field_offset);
1099     Runtime::Current()->RecordWriteField32(this, field_offset, old_value, kIsVolatile);
1100   }
1101   if (kVerifyFlags & kVerifyThis) {
1102     VerifyObject(this);
1103   }
1104   uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
1105   int32_t* addr = reinterpret_cast<int32_t*>(raw_addr);
1106   accessor->Access(addr);
1107 }
1108 
1109 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
UpdateField64ViaAccessor(MemberOffset field_offset,Accessor<int64_t> * accessor)1110 inline void Object::UpdateField64ViaAccessor(MemberOffset field_offset,
1111                                              Accessor<int64_t>* accessor) {
1112   if (kCheckTransaction) {
1113     DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
1114   }
1115   if (kTransactionActive) {
1116     static const bool kIsVolatile = true;
1117     int64_t old_value = GetField64<kVerifyFlags, kIsVolatile>(field_offset);
1118     Runtime::Current()->RecordWriteField64(this, field_offset, old_value, kIsVolatile);
1119   }
1120   if (kVerifyFlags & kVerifyThis) {
1121     VerifyObject(this);
1122   }
1123   uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
1124   int64_t* addr = reinterpret_cast<int64_t*>(raw_addr);
1125   accessor->Access(addr);
1126 }
1127 
1128 template<bool kIsStatic,
1129          VerifyObjectFlags kVerifyFlags,
1130          ReadBarrierOption kReadBarrierOption,
1131          typename Visitor>
VisitFieldsReferences(uint32_t ref_offsets,const Visitor & visitor)1132 inline void Object::VisitFieldsReferences(uint32_t ref_offsets, const Visitor& visitor) {
1133   if (!kIsStatic && (ref_offsets != mirror::Class::kClassWalkSuper)) {
1134     // Instance fields and not the slow-path.
1135     uint32_t field_offset = mirror::kObjectHeaderSize;
1136     while (ref_offsets != 0) {
1137       if ((ref_offsets & 1) != 0) {
1138         visitor(this, MemberOffset(field_offset), kIsStatic);
1139       }
1140       ref_offsets >>= 1;
1141       field_offset += sizeof(mirror::HeapReference<mirror::Object>);
1142     }
1143   } else {
1144     // There is no reference offset bitmap. In the non-static case, walk up the class
1145     // inheritance hierarchy and find reference offsets the hard way. In the static case, just
1146     // consider this class.
1147     for (ObjPtr<Class> klass = kIsStatic
1148             ? AsClass<kVerifyFlags, kReadBarrierOption>()
1149             : GetClass<kVerifyFlags, kReadBarrierOption>();
1150         klass != nullptr;
1151         klass = kIsStatic ? nullptr : klass->GetSuperClass<kVerifyFlags, kReadBarrierOption>()) {
1152       const size_t num_reference_fields =
1153           kIsStatic ? klass->NumReferenceStaticFields() : klass->NumReferenceInstanceFields();
1154       if (num_reference_fields == 0u) {
1155         continue;
1156       }
1157       // Presumably GC can happen when we are cross compiling, it should not cause performance
1158       // problems to do pointer size logic.
1159       MemberOffset field_offset = kIsStatic
1160           ? klass->GetFirstReferenceStaticFieldOffset<kVerifyFlags, kReadBarrierOption>(
1161               Runtime::Current()->GetClassLinker()->GetImagePointerSize())
1162           : klass->GetFirstReferenceInstanceFieldOffset<kVerifyFlags, kReadBarrierOption>();
1163       for (size_t i = 0u; i < num_reference_fields; ++i) {
1164         // TODO: Do a simpler check?
1165         if (field_offset.Uint32Value() != ClassOffset().Uint32Value()) {
1166           visitor(this, field_offset, kIsStatic);
1167         }
1168         field_offset = MemberOffset(field_offset.Uint32Value() +
1169                                     sizeof(mirror::HeapReference<mirror::Object>));
1170       }
1171     }
1172   }
1173 }
1174 
1175 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption, typename Visitor>
VisitInstanceFieldsReferences(ObjPtr<Class> klass,const Visitor & visitor)1176 inline void Object::VisitInstanceFieldsReferences(ObjPtr<Class> klass, const Visitor& visitor) {
1177   VisitFieldsReferences<false, kVerifyFlags, kReadBarrierOption>(
1178       klass->GetReferenceInstanceOffsets<kVerifyFlags>(), visitor);
1179 }
1180 
1181 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption, typename Visitor>
VisitStaticFieldsReferences(ObjPtr<Class> klass,const Visitor & visitor)1182 inline void Object::VisitStaticFieldsReferences(ObjPtr<Class> klass, const Visitor& visitor) {
1183   DCHECK(!klass->IsTemp());
1184   klass->VisitFieldsReferences<true, kVerifyFlags, kReadBarrierOption>(0, visitor);
1185 }
1186 
1187 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
IsClassLoader()1188 inline bool Object::IsClassLoader() {
1189   return GetClass<kVerifyFlags, kReadBarrierOption>()->IsClassLoaderClass();
1190 }
1191 
1192 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
AsClassLoader()1193 inline mirror::ClassLoader* Object::AsClassLoader() {
1194   DCHECK((IsClassLoader<kVerifyFlags, kReadBarrierOption>()));
1195   return down_cast<mirror::ClassLoader*>(this);
1196 }
1197 
1198 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
IsDexCache()1199 inline bool Object::IsDexCache() {
1200   return GetClass<kVerifyFlags, kReadBarrierOption>()->IsDexCacheClass();
1201 }
1202 
1203 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
AsDexCache()1204 inline mirror::DexCache* Object::AsDexCache() {
1205   DCHECK((IsDexCache<kVerifyFlags, kReadBarrierOption>()));
1206   return down_cast<mirror::DexCache*>(this);
1207 }
1208 
1209 }  // namespace mirror
1210 }  // namespace art
1211 
1212 #endif  // ART_RUNTIME_MIRROR_OBJECT_INL_H_
1213