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 "class_linker.h"
28 #include "lock_word-inl.h"
29 #include "monitor.h"
30 #include "object_array-inl.h"
31 #include "read_barrier-inl.h"
32 #include "reference.h"
33 #include "runtime.h"
34 #include "string-inl.h"
35 #include "throwable.h"
36
37 namespace art {
38 namespace mirror {
39
ClassSize(size_t pointer_size)40 inline uint32_t Object::ClassSize(size_t pointer_size) {
41 uint32_t vtable_entries = kVTableLength;
42 return Class::ComputeClassSize(true, vtable_entries, 0, 0, 0, 0, 0, pointer_size);
43 }
44
45 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
GetClass()46 inline Class* Object::GetClass() {
47 return GetFieldObject<Class, kVerifyFlags, kReadBarrierOption>(
48 OFFSET_OF_OBJECT_MEMBER(Object, klass_));
49 }
50
51 template<VerifyObjectFlags kVerifyFlags>
SetClass(Class * new_klass)52 inline void Object::SetClass(Class* new_klass) {
53 // new_klass may be null prior to class linker initialization.
54 // We don't mark the card as this occurs as part of object allocation. Not all objects have
55 // backing cards, such as large objects.
56 // We use non transactional version since we can't undo this write. We also disable checking as
57 // we may run in transaction mode here.
58 SetFieldObjectWithoutWriteBarrier<false, false,
59 static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis)>(
60 OFFSET_OF_OBJECT_MEMBER(Object, klass_), new_klass);
61 }
62
GetLockWord(bool as_volatile)63 inline LockWord Object::GetLockWord(bool as_volatile) {
64 if (as_volatile) {
65 return LockWord(GetField32Volatile(OFFSET_OF_OBJECT_MEMBER(Object, monitor_)));
66 }
67 return LockWord(GetField32(OFFSET_OF_OBJECT_MEMBER(Object, monitor_)));
68 }
69
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>(OFFSET_OF_OBJECT_MEMBER(Object, monitor_), new_val.GetValue());
74 } else {
75 SetField32<false, false>(OFFSET_OF_OBJECT_MEMBER(Object, monitor_), new_val.GetValue());
76 }
77 }
78
CasLockWordWeakSequentiallyConsistent(LockWord old_val,LockWord new_val)79 inline bool Object::CasLockWordWeakSequentiallyConsistent(LockWord old_val, LockWord new_val) {
80 // Force use of non-transactional mode and do not check.
81 return CasFieldWeakSequentiallyConsistent32<false, false>(
82 OFFSET_OF_OBJECT_MEMBER(Object, monitor_), old_val.GetValue(), new_val.GetValue());
83 }
84
CasLockWordWeakRelaxed(LockWord old_val,LockWord new_val)85 inline bool Object::CasLockWordWeakRelaxed(LockWord old_val, LockWord new_val) {
86 // Force use of non-transactional mode and do not check.
87 return CasFieldWeakRelaxed32<false, false>(
88 OFFSET_OF_OBJECT_MEMBER(Object, monitor_), old_val.GetValue(), new_val.GetValue());
89 }
90
GetLockOwnerThreadId()91 inline uint32_t Object::GetLockOwnerThreadId() {
92 return Monitor::GetLockOwnerThreadId(this);
93 }
94
MonitorEnter(Thread * self)95 inline mirror::Object* Object::MonitorEnter(Thread* self) {
96 return Monitor::MonitorEnter(self, this);
97 }
98
MonitorExit(Thread * self)99 inline bool Object::MonitorExit(Thread* self) {
100 return Monitor::MonitorExit(self, this);
101 }
102
Notify(Thread * self)103 inline void Object::Notify(Thread* self) {
104 Monitor::Notify(self, this);
105 }
106
NotifyAll(Thread * self)107 inline void Object::NotifyAll(Thread* self) {
108 Monitor::NotifyAll(self, this);
109 }
110
Wait(Thread * self)111 inline void Object::Wait(Thread* self) {
112 Monitor::Wait(self, this, 0, 0, true, kWaiting);
113 }
114
Wait(Thread * self,int64_t ms,int32_t ns)115 inline void Object::Wait(Thread* self, int64_t ms, int32_t ns) {
116 Monitor::Wait(self, this, ms, ns, true, kTimedWaiting);
117 }
118
GetReadBarrierPointer()119 inline Object* Object::GetReadBarrierPointer() {
120 #ifdef USE_BAKER_READ_BARRIER
121 DCHECK(kUseBakerReadBarrier);
122 return reinterpret_cast<Object*>(GetLockWord(false).ReadBarrierState());
123 #elif USE_BROOKS_READ_BARRIER
124 DCHECK(kUseBrooksReadBarrier);
125 return GetFieldObject<Object, kVerifyNone, kWithoutReadBarrier>(
126 OFFSET_OF_OBJECT_MEMBER(Object, x_rb_ptr_));
127 #else
128 LOG(FATAL) << "Unreachable";
129 UNREACHABLE();
130 #endif
131 }
132
SetReadBarrierPointer(Object * rb_ptr)133 inline void Object::SetReadBarrierPointer(Object* rb_ptr) {
134 #ifdef USE_BAKER_READ_BARRIER
135 DCHECK(kUseBakerReadBarrier);
136 DCHECK_EQ(reinterpret_cast<uint64_t>(rb_ptr) >> 32, 0U);
137 LockWord lw = GetLockWord(false);
138 lw.SetReadBarrierState(static_cast<uint32_t>(reinterpret_cast<uintptr_t>(rb_ptr)));
139 SetLockWord(lw, false);
140 #elif USE_BROOKS_READ_BARRIER
141 DCHECK(kUseBrooksReadBarrier);
142 // We don't mark the card as this occurs as part of object allocation. Not all objects have
143 // backing cards, such as large objects.
144 SetFieldObjectWithoutWriteBarrier<false, false, kVerifyNone>(
145 OFFSET_OF_OBJECT_MEMBER(Object, x_rb_ptr_), rb_ptr);
146 #else
147 LOG(FATAL) << "Unreachable";
148 UNREACHABLE();
149 UNUSED(rb_ptr);
150 #endif
151 }
152
AtomicSetReadBarrierPointer(Object * expected_rb_ptr,Object * rb_ptr)153 inline bool Object::AtomicSetReadBarrierPointer(Object* expected_rb_ptr, Object* rb_ptr) {
154 #ifdef USE_BAKER_READ_BARRIER
155 DCHECK(kUseBakerReadBarrier);
156 DCHECK_EQ(reinterpret_cast<uint64_t>(expected_rb_ptr) >> 32, 0U);
157 DCHECK_EQ(reinterpret_cast<uint64_t>(rb_ptr) >> 32, 0U);
158 LockWord expected_lw;
159 LockWord new_lw;
160 do {
161 LockWord lw = GetLockWord(false);
162 if (UNLIKELY(reinterpret_cast<Object*>(lw.ReadBarrierState()) != expected_rb_ptr)) {
163 // Lost the race.
164 return false;
165 }
166 expected_lw = lw;
167 expected_lw.SetReadBarrierState(
168 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(expected_rb_ptr)));
169 new_lw = lw;
170 new_lw.SetReadBarrierState(static_cast<uint32_t>(reinterpret_cast<uintptr_t>(rb_ptr)));
171 } while (!CasLockWordWeakSequentiallyConsistent(expected_lw, new_lw));
172 return true;
173 #elif USE_BROOKS_READ_BARRIER
174 DCHECK(kUseBrooksReadBarrier);
175 MemberOffset offset = OFFSET_OF_OBJECT_MEMBER(Object, x_rb_ptr_);
176 uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + offset.SizeValue();
177 Atomic<uint32_t>* atomic_rb_ptr = reinterpret_cast<Atomic<uint32_t>*>(raw_addr);
178 HeapReference<Object> expected_ref(HeapReference<Object>::FromMirrorPtr(expected_rb_ptr));
179 HeapReference<Object> new_ref(HeapReference<Object>::FromMirrorPtr(rb_ptr));
180 do {
181 if (UNLIKELY(atomic_rb_ptr->LoadRelaxed() != expected_ref.reference_)) {
182 // Lost the race.
183 return false;
184 }
185 } while (!atomic_rb_ptr->CompareExchangeWeakSequentiallyConsistent(expected_ref.reference_,
186 new_ref.reference_));
187 return true;
188 #else
189 UNUSED(expected_rb_ptr, rb_ptr);
190 LOG(FATAL) << "Unreachable";
191 UNREACHABLE();
192 #endif
193 }
194
AssertReadBarrierPointer()195 inline void Object::AssertReadBarrierPointer() const {
196 if (kUseBakerReadBarrier) {
197 Object* obj = const_cast<Object*>(this);
198 DCHECK(obj->GetReadBarrierPointer() == nullptr)
199 << "Bad Baker pointer: obj=" << reinterpret_cast<void*>(obj)
200 << " ptr=" << reinterpret_cast<void*>(obj->GetReadBarrierPointer());
201 } else {
202 CHECK(kUseBrooksReadBarrier);
203 Object* obj = const_cast<Object*>(this);
204 DCHECK_EQ(obj, obj->GetReadBarrierPointer())
205 << "Bad Brooks pointer: obj=" << reinterpret_cast<void*>(obj)
206 << " ptr=" << reinterpret_cast<void*>(obj->GetReadBarrierPointer());
207 }
208 }
209
210 template<VerifyObjectFlags kVerifyFlags>
VerifierInstanceOf(Class * klass)211 inline bool Object::VerifierInstanceOf(Class* klass) {
212 DCHECK(klass != nullptr);
213 DCHECK(GetClass<kVerifyFlags>() != nullptr);
214 return klass->IsInterface() || InstanceOf(klass);
215 }
216
217 template<VerifyObjectFlags kVerifyFlags>
InstanceOf(Class * klass)218 inline bool Object::InstanceOf(Class* klass) {
219 DCHECK(klass != nullptr);
220 DCHECK(GetClass<kVerifyNone>() != nullptr);
221 return klass->IsAssignableFrom(GetClass<kVerifyFlags>());
222 }
223
224 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
IsClass()225 inline bool Object::IsClass() {
226 Class* java_lang_Class = GetClass<kVerifyFlags, kReadBarrierOption>()->
227 template GetClass<kVerifyFlags, kReadBarrierOption>();
228 return GetClass<static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis),
229 kReadBarrierOption>() == java_lang_Class;
230 }
231
232 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
AsClass()233 inline Class* Object::AsClass() {
234 DCHECK((IsClass<kVerifyFlags, kReadBarrierOption>()));
235 return down_cast<Class*>(this);
236 }
237
238 template<VerifyObjectFlags kVerifyFlags>
IsObjectArray()239 inline bool Object::IsObjectArray() {
240 constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
241 return IsArrayInstance<kVerifyFlags>() &&
242 !GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitive();
243 }
244
245 template<class T, VerifyObjectFlags kVerifyFlags>
AsObjectArray()246 inline ObjectArray<T>* Object::AsObjectArray() {
247 DCHECK(IsObjectArray<kVerifyFlags>());
248 return down_cast<ObjectArray<T>*>(this);
249 }
250
251 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
IsArrayInstance()252 inline bool Object::IsArrayInstance() {
253 return GetClass<kVerifyFlags, kReadBarrierOption>()->
254 template IsArrayClass<kVerifyFlags, kReadBarrierOption>();
255 }
256
257 template<VerifyObjectFlags kVerifyFlags>
IsReferenceInstance()258 inline bool Object::IsReferenceInstance() {
259 return GetClass<kVerifyFlags>()->IsTypeOfReferenceClass();
260 }
261
262 template<VerifyObjectFlags kVerifyFlags>
AsReference()263 inline Reference* Object::AsReference() {
264 DCHECK(IsReferenceInstance<kVerifyFlags>());
265 return down_cast<Reference*>(this);
266 }
267
268 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
AsArray()269 inline Array* Object::AsArray() {
270 DCHECK((IsArrayInstance<kVerifyFlags, kReadBarrierOption>()));
271 return down_cast<Array*>(this);
272 }
273
274 template<VerifyObjectFlags kVerifyFlags>
AsBooleanArray()275 inline BooleanArray* Object::AsBooleanArray() {
276 constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
277 DCHECK(GetClass<kVerifyFlags>()->IsArrayClass());
278 DCHECK(GetClass<kNewFlags>()->GetComponentType()->IsPrimitiveBoolean());
279 return down_cast<BooleanArray*>(this);
280 }
281
282 template<VerifyObjectFlags kVerifyFlags>
AsByteArray()283 inline ByteArray* Object::AsByteArray() {
284 constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
285 DCHECK(GetClass<kVerifyFlags>()->IsArrayClass());
286 DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveByte());
287 return down_cast<ByteArray*>(this);
288 }
289
290 template<VerifyObjectFlags kVerifyFlags>
AsByteSizedArray()291 inline ByteArray* Object::AsByteSizedArray() {
292 constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
293 DCHECK(GetClass<kVerifyFlags>()->IsArrayClass());
294 DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveByte() ||
295 GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveBoolean());
296 return down_cast<ByteArray*>(this);
297 }
298
299 template<VerifyObjectFlags kVerifyFlags>
AsCharArray()300 inline CharArray* Object::AsCharArray() {
301 constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
302 DCHECK(GetClass<kVerifyFlags>()->IsArrayClass());
303 DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveChar());
304 return down_cast<CharArray*>(this);
305 }
306
307 template<VerifyObjectFlags kVerifyFlags>
AsShortArray()308 inline ShortArray* Object::AsShortArray() {
309 constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
310 DCHECK(GetClass<kVerifyFlags>()->IsArrayClass());
311 DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveShort());
312 return down_cast<ShortArray*>(this);
313 }
314
315 template<VerifyObjectFlags kVerifyFlags>
AsShortSizedArray()316 inline ShortArray* Object::AsShortSizedArray() {
317 constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
318 DCHECK(GetClass<kVerifyFlags>()->IsArrayClass());
319 DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveShort() ||
320 GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveChar());
321 return down_cast<ShortArray*>(this);
322 }
323
324 template<VerifyObjectFlags kVerifyFlags>
IsIntArray()325 inline bool Object::IsIntArray() {
326 constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
327 auto* component_type = GetClass<kVerifyFlags>()->GetComponentType();
328 return component_type != nullptr && component_type->template IsPrimitiveInt<kNewFlags>();
329 }
330
331 template<VerifyObjectFlags kVerifyFlags>
AsIntArray()332 inline IntArray* Object::AsIntArray() {
333 DCHECK(IsIntArray<kVerifyFlags>());
334 return down_cast<IntArray*>(this);
335 }
336
337 template<VerifyObjectFlags kVerifyFlags>
IsLongArray()338 inline bool Object::IsLongArray() {
339 constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
340 auto* component_type = GetClass<kVerifyFlags>()->GetComponentType();
341 return component_type != nullptr && component_type->template IsPrimitiveLong<kNewFlags>();
342 }
343
344 template<VerifyObjectFlags kVerifyFlags>
AsLongArray()345 inline LongArray* Object::AsLongArray() {
346 DCHECK(IsLongArray<kVerifyFlags>());
347 return down_cast<LongArray*>(this);
348 }
349
350 template<VerifyObjectFlags kVerifyFlags>
IsFloatArray()351 inline bool Object::IsFloatArray() {
352 constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
353 auto* component_type = GetClass<kVerifyFlags>()->GetComponentType();
354 return component_type != nullptr && component_type->template IsPrimitiveFloat<kNewFlags>();
355 }
356
357 template<VerifyObjectFlags kVerifyFlags>
AsFloatArray()358 inline FloatArray* Object::AsFloatArray() {
359 DCHECK(IsFloatArray<kVerifyFlags>());
360 constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
361 DCHECK(GetClass<kVerifyFlags>()->IsArrayClass());
362 DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveFloat());
363 return down_cast<FloatArray*>(this);
364 }
365
366 template<VerifyObjectFlags kVerifyFlags>
IsDoubleArray()367 inline bool Object::IsDoubleArray() {
368 constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
369 auto* component_type = GetClass<kVerifyFlags>()->GetComponentType();
370 return component_type != nullptr && component_type->template IsPrimitiveDouble<kNewFlags>();
371 }
372
373 template<VerifyObjectFlags kVerifyFlags>
AsDoubleArray()374 inline DoubleArray* Object::AsDoubleArray() {
375 DCHECK(IsDoubleArray<kVerifyFlags>());
376 constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
377 DCHECK(GetClass<kVerifyFlags>()->IsArrayClass());
378 DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveDouble());
379 return down_cast<DoubleArray*>(this);
380 }
381
382 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
IsString()383 inline bool Object::IsString() {
384 return GetClass<kVerifyFlags, kReadBarrierOption>()->IsStringClass();
385 }
386
387 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
AsString()388 inline String* Object::AsString() {
389 DCHECK((IsString<kVerifyFlags, kReadBarrierOption>()));
390 return down_cast<String*>(this);
391 }
392
393 template<VerifyObjectFlags kVerifyFlags>
AsThrowable()394 inline Throwable* Object::AsThrowable() {
395 DCHECK(GetClass<kVerifyFlags>()->IsThrowableClass());
396 return down_cast<Throwable*>(this);
397 }
398
399 template<VerifyObjectFlags kVerifyFlags>
IsWeakReferenceInstance()400 inline bool Object::IsWeakReferenceInstance() {
401 return GetClass<kVerifyFlags>()->IsWeakReferenceClass();
402 }
403
404 template<VerifyObjectFlags kVerifyFlags>
IsSoftReferenceInstance()405 inline bool Object::IsSoftReferenceInstance() {
406 return GetClass<kVerifyFlags>()->IsSoftReferenceClass();
407 }
408
409 template<VerifyObjectFlags kVerifyFlags>
IsFinalizerReferenceInstance()410 inline bool Object::IsFinalizerReferenceInstance() {
411 return GetClass<kVerifyFlags>()->IsFinalizerReferenceClass();
412 }
413
414 template<VerifyObjectFlags kVerifyFlags>
AsFinalizerReference()415 inline FinalizerReference* Object::AsFinalizerReference() {
416 DCHECK(IsFinalizerReferenceInstance<kVerifyFlags>());
417 return down_cast<FinalizerReference*>(this);
418 }
419
420 template<VerifyObjectFlags kVerifyFlags>
IsPhantomReferenceInstance()421 inline bool Object::IsPhantomReferenceInstance() {
422 return GetClass<kVerifyFlags>()->IsPhantomReferenceClass();
423 }
424
425 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
SizeOf()426 inline size_t Object::SizeOf() {
427 size_t result;
428 constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
429 if (IsArrayInstance<kVerifyFlags, kReadBarrierOption>()) {
430 result = AsArray<kNewFlags, kReadBarrierOption>()->
431 template SizeOf<kNewFlags, kReadBarrierOption>();
432 } else if (IsClass<kNewFlags, kReadBarrierOption>()) {
433 result = AsClass<kNewFlags, kReadBarrierOption>()->
434 template SizeOf<kNewFlags, kReadBarrierOption>();
435 } else if (GetClass<kNewFlags, kReadBarrierOption>()->IsStringClass()) {
436 result = AsString<kNewFlags, kReadBarrierOption>()->
437 template SizeOf<kNewFlags>();
438 } else {
439 result = GetClass<kNewFlags, kReadBarrierOption>()->
440 template GetObjectSize<kNewFlags, kReadBarrierOption>();
441 }
442 DCHECK_GE(result, sizeof(Object))
443 << " class=" << PrettyTypeOf(GetClass<kNewFlags, kReadBarrierOption>());
444 return result;
445 }
446
447 template<VerifyObjectFlags kVerifyFlags, bool kIsVolatile>
GetFieldBoolean(MemberOffset field_offset)448 inline uint8_t Object::GetFieldBoolean(MemberOffset field_offset) {
449 if (kVerifyFlags & kVerifyThis) {
450 VerifyObject(this);
451 }
452 return GetField<uint8_t, kIsVolatile>(field_offset);
453 }
454
455 template<VerifyObjectFlags kVerifyFlags, bool kIsVolatile>
GetFieldByte(MemberOffset field_offset)456 inline int8_t Object::GetFieldByte(MemberOffset field_offset) {
457 if (kVerifyFlags & kVerifyThis) {
458 VerifyObject(this);
459 }
460 return GetField<int8_t, kIsVolatile>(field_offset);
461 }
462
463 template<VerifyObjectFlags kVerifyFlags>
GetFieldBooleanVolatile(MemberOffset field_offset)464 inline uint8_t Object::GetFieldBooleanVolatile(MemberOffset field_offset) {
465 return GetFieldBoolean<kVerifyFlags, true>(field_offset);
466 }
467
468 template<VerifyObjectFlags kVerifyFlags>
GetFieldByteVolatile(MemberOffset field_offset)469 inline int8_t Object::GetFieldByteVolatile(MemberOffset field_offset) {
470 return GetFieldByte<kVerifyFlags, true>(field_offset);
471 }
472
473 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags,
474 bool kIsVolatile>
SetFieldBoolean(MemberOffset field_offset,uint8_t new_value)475 inline void Object::SetFieldBoolean(MemberOffset field_offset, uint8_t new_value)
476 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
477 if (kCheckTransaction) {
478 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
479 }
480 if (kTransactionActive) {
481 Runtime::Current()->RecordWriteFieldBoolean(this, field_offset,
482 GetFieldBoolean<kVerifyFlags, kIsVolatile>(field_offset),
483 kIsVolatile);
484 }
485 if (kVerifyFlags & kVerifyThis) {
486 VerifyObject(this);
487 }
488 SetField<uint8_t, kIsVolatile>(field_offset, new_value);
489 }
490
491 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags,
492 bool kIsVolatile>
SetFieldByte(MemberOffset field_offset,int8_t new_value)493 inline void Object::SetFieldByte(MemberOffset field_offset, int8_t new_value)
494 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
495 if (kCheckTransaction) {
496 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
497 }
498 if (kTransactionActive) {
499 Runtime::Current()->RecordWriteFieldByte(this, field_offset,
500 GetFieldByte<kVerifyFlags, kIsVolatile>(field_offset),
501 kIsVolatile);
502 }
503 if (kVerifyFlags & kVerifyThis) {
504 VerifyObject(this);
505 }
506 SetField<int8_t, kIsVolatile>(field_offset, new_value);
507 }
508
509 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
SetFieldBooleanVolatile(MemberOffset field_offset,uint8_t new_value)510 inline void Object::SetFieldBooleanVolatile(MemberOffset field_offset, uint8_t new_value) {
511 return SetFieldBoolean<kTransactionActive, kCheckTransaction, kVerifyFlags, true>(
512 field_offset, new_value);
513 }
514
515 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
SetFieldByteVolatile(MemberOffset field_offset,int8_t new_value)516 inline void Object::SetFieldByteVolatile(MemberOffset field_offset, int8_t new_value) {
517 return SetFieldByte<kTransactionActive, kCheckTransaction, kVerifyFlags, true>(
518 field_offset, new_value);
519 }
520
521 template<VerifyObjectFlags kVerifyFlags, bool kIsVolatile>
GetFieldChar(MemberOffset field_offset)522 inline uint16_t Object::GetFieldChar(MemberOffset field_offset) {
523 if (kVerifyFlags & kVerifyThis) {
524 VerifyObject(this);
525 }
526 return GetField<uint16_t, kIsVolatile>(field_offset);
527 }
528
529 template<VerifyObjectFlags kVerifyFlags, bool kIsVolatile>
GetFieldShort(MemberOffset field_offset)530 inline int16_t Object::GetFieldShort(MemberOffset field_offset) {
531 if (kVerifyFlags & kVerifyThis) {
532 VerifyObject(this);
533 }
534 return GetField<int16_t, kIsVolatile>(field_offset);
535 }
536
537 template<VerifyObjectFlags kVerifyFlags>
GetFieldCharVolatile(MemberOffset field_offset)538 inline uint16_t Object::GetFieldCharVolatile(MemberOffset field_offset) {
539 return GetFieldChar<kVerifyFlags, true>(field_offset);
540 }
541
542 template<VerifyObjectFlags kVerifyFlags>
GetFieldShortVolatile(MemberOffset field_offset)543 inline int16_t Object::GetFieldShortVolatile(MemberOffset field_offset) {
544 return GetFieldShort<kVerifyFlags, true>(field_offset);
545 }
546
547 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags,
548 bool kIsVolatile>
SetFieldChar(MemberOffset field_offset,uint16_t new_value)549 inline void Object::SetFieldChar(MemberOffset field_offset, uint16_t new_value) {
550 if (kCheckTransaction) {
551 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
552 }
553 if (kTransactionActive) {
554 Runtime::Current()->RecordWriteFieldChar(this, field_offset,
555 GetFieldChar<kVerifyFlags, kIsVolatile>(field_offset),
556 kIsVolatile);
557 }
558 if (kVerifyFlags & kVerifyThis) {
559 VerifyObject(this);
560 }
561 SetField<uint16_t, kIsVolatile>(field_offset, new_value);
562 }
563
564 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags,
565 bool kIsVolatile>
SetFieldShort(MemberOffset field_offset,int16_t new_value)566 inline void Object::SetFieldShort(MemberOffset field_offset, int16_t new_value) {
567 if (kCheckTransaction) {
568 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
569 }
570 if (kTransactionActive) {
571 Runtime::Current()->RecordWriteFieldChar(this, field_offset,
572 GetFieldShort<kVerifyFlags, kIsVolatile>(field_offset),
573 kIsVolatile);
574 }
575 if (kVerifyFlags & kVerifyThis) {
576 VerifyObject(this);
577 }
578 SetField<int16_t, kIsVolatile>(field_offset, new_value);
579 }
580
581 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
SetFieldCharVolatile(MemberOffset field_offset,uint16_t new_value)582 inline void Object::SetFieldCharVolatile(MemberOffset field_offset, uint16_t new_value) {
583 return SetFieldChar<kTransactionActive, kCheckTransaction, kVerifyFlags, true>(
584 field_offset, new_value);
585 }
586
587 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
SetFieldShortVolatile(MemberOffset field_offset,int16_t new_value)588 inline void Object::SetFieldShortVolatile(MemberOffset field_offset, int16_t new_value) {
589 return SetFieldShort<kTransactionActive, kCheckTransaction, kVerifyFlags, true>(
590 field_offset, new_value);
591 }
592
593 template<VerifyObjectFlags kVerifyFlags, bool kIsVolatile>
GetField32(MemberOffset field_offset)594 inline int32_t Object::GetField32(MemberOffset field_offset) {
595 if (kVerifyFlags & kVerifyThis) {
596 VerifyObject(this);
597 }
598 return GetField<int32_t, kIsVolatile>(field_offset);
599 }
600
601 template<VerifyObjectFlags kVerifyFlags>
GetField32Volatile(MemberOffset field_offset)602 inline int32_t Object::GetField32Volatile(MemberOffset field_offset) {
603 return GetField32<kVerifyFlags, true>(field_offset);
604 }
605
606 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags,
607 bool kIsVolatile>
SetField32(MemberOffset field_offset,int32_t new_value)608 inline void Object::SetField32(MemberOffset field_offset, int32_t new_value) {
609 if (kCheckTransaction) {
610 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
611 }
612 if (kTransactionActive) {
613 Runtime::Current()->RecordWriteField32(this, field_offset,
614 GetField32<kVerifyFlags, kIsVolatile>(field_offset),
615 kIsVolatile);
616 }
617 if (kVerifyFlags & kVerifyThis) {
618 VerifyObject(this);
619 }
620 SetField<int32_t, kIsVolatile>(field_offset, new_value);
621 }
622
623 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
SetField32Volatile(MemberOffset field_offset,int32_t new_value)624 inline void Object::SetField32Volatile(MemberOffset field_offset, int32_t new_value) {
625 SetField32<kTransactionActive, kCheckTransaction, kVerifyFlags, true>(field_offset, new_value);
626 }
627
628 // TODO: Pass memory_order_ and strong/weak as arguments to avoid code duplication?
629
630 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
CasFieldWeakSequentiallyConsistent32(MemberOffset field_offset,int32_t old_value,int32_t new_value)631 inline bool Object::CasFieldWeakSequentiallyConsistent32(MemberOffset field_offset,
632 int32_t old_value, int32_t new_value) {
633 if (kCheckTransaction) {
634 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
635 }
636 if (kTransactionActive) {
637 Runtime::Current()->RecordWriteField32(this, field_offset, old_value, true);
638 }
639 if (kVerifyFlags & kVerifyThis) {
640 VerifyObject(this);
641 }
642 uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
643 AtomicInteger* atomic_addr = reinterpret_cast<AtomicInteger*>(raw_addr);
644
645 return atomic_addr->CompareExchangeWeakSequentiallyConsistent(old_value, new_value);
646 }
647
648 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
CasFieldWeakRelaxed32(MemberOffset field_offset,int32_t old_value,int32_t new_value)649 inline bool Object::CasFieldWeakRelaxed32(MemberOffset field_offset,
650 int32_t old_value, int32_t new_value) {
651 if (kCheckTransaction) {
652 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
653 }
654 if (kTransactionActive) {
655 Runtime::Current()->RecordWriteField32(this, field_offset, old_value, true);
656 }
657 if (kVerifyFlags & kVerifyThis) {
658 VerifyObject(this);
659 }
660 uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
661 AtomicInteger* atomic_addr = reinterpret_cast<AtomicInteger*>(raw_addr);
662
663 return atomic_addr->CompareExchangeWeakRelaxed(old_value, new_value);
664 }
665
666 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
CasFieldStrongSequentiallyConsistent32(MemberOffset field_offset,int32_t old_value,int32_t new_value)667 inline bool Object::CasFieldStrongSequentiallyConsistent32(MemberOffset field_offset,
668 int32_t old_value, int32_t new_value) {
669 if (kCheckTransaction) {
670 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
671 }
672 if (kTransactionActive) {
673 Runtime::Current()->RecordWriteField32(this, field_offset, old_value, true);
674 }
675 if (kVerifyFlags & kVerifyThis) {
676 VerifyObject(this);
677 }
678 uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
679 AtomicInteger* atomic_addr = reinterpret_cast<AtomicInteger*>(raw_addr);
680
681 return atomic_addr->CompareExchangeStrongSequentiallyConsistent(old_value, new_value);
682 }
683
684 template<VerifyObjectFlags kVerifyFlags, bool kIsVolatile>
GetField64(MemberOffset field_offset)685 inline int64_t Object::GetField64(MemberOffset field_offset) {
686 if (kVerifyFlags & kVerifyThis) {
687 VerifyObject(this);
688 }
689 return GetField<int64_t, kIsVolatile>(field_offset);
690 }
691
692 template<VerifyObjectFlags kVerifyFlags>
GetField64Volatile(MemberOffset field_offset)693 inline int64_t Object::GetField64Volatile(MemberOffset field_offset) {
694 return GetField64<kVerifyFlags, true>(field_offset);
695 }
696
697 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags,
698 bool kIsVolatile>
SetField64(MemberOffset field_offset,int64_t new_value)699 inline void Object::SetField64(MemberOffset field_offset, int64_t new_value) {
700 if (kCheckTransaction) {
701 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
702 }
703 if (kTransactionActive) {
704 Runtime::Current()->RecordWriteField64(this, field_offset,
705 GetField64<kVerifyFlags, kIsVolatile>(field_offset),
706 kIsVolatile);
707 }
708 if (kVerifyFlags & kVerifyThis) {
709 VerifyObject(this);
710 }
711 SetField<int64_t, kIsVolatile>(field_offset, new_value);
712 }
713
714 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
SetField64Volatile(MemberOffset field_offset,int64_t new_value)715 inline void Object::SetField64Volatile(MemberOffset field_offset, int64_t new_value) {
716 return SetField64<kTransactionActive, kCheckTransaction, kVerifyFlags, true>(field_offset,
717 new_value);
718 }
719
720 template<typename kSize, bool kIsVolatile>
SetField(MemberOffset field_offset,kSize new_value)721 inline void Object::SetField(MemberOffset field_offset, kSize new_value) {
722 uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
723 kSize* addr = reinterpret_cast<kSize*>(raw_addr);
724 if (kIsVolatile) {
725 reinterpret_cast<Atomic<kSize>*>(addr)->StoreSequentiallyConsistent(new_value);
726 } else {
727 reinterpret_cast<Atomic<kSize>*>(addr)->StoreJavaData(new_value);
728 }
729 }
730
731 template<typename kSize, bool kIsVolatile>
GetField(MemberOffset field_offset)732 inline kSize Object::GetField(MemberOffset field_offset) {
733 const uint8_t* raw_addr = reinterpret_cast<const uint8_t*>(this) + field_offset.Int32Value();
734 const kSize* addr = reinterpret_cast<const kSize*>(raw_addr);
735 if (kIsVolatile) {
736 return reinterpret_cast<const Atomic<kSize>*>(addr)->LoadSequentiallyConsistent();
737 } else {
738 return reinterpret_cast<const Atomic<kSize>*>(addr)->LoadJavaData();
739 }
740 }
741
742 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
CasFieldWeakSequentiallyConsistent64(MemberOffset field_offset,int64_t old_value,int64_t new_value)743 inline bool Object::CasFieldWeakSequentiallyConsistent64(MemberOffset field_offset,
744 int64_t old_value, int64_t new_value) {
745 if (kCheckTransaction) {
746 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
747 }
748 if (kTransactionActive) {
749 Runtime::Current()->RecordWriteField64(this, field_offset, old_value, true);
750 }
751 if (kVerifyFlags & kVerifyThis) {
752 VerifyObject(this);
753 }
754 uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
755 Atomic<int64_t>* atomic_addr = reinterpret_cast<Atomic<int64_t>*>(raw_addr);
756 return atomic_addr->CompareExchangeWeakSequentiallyConsistent(old_value, new_value);
757 }
758
759 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
CasFieldStrongSequentiallyConsistent64(MemberOffset field_offset,int64_t old_value,int64_t new_value)760 inline bool Object::CasFieldStrongSequentiallyConsistent64(MemberOffset field_offset,
761 int64_t old_value, int64_t new_value) {
762 if (kCheckTransaction) {
763 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
764 }
765 if (kTransactionActive) {
766 Runtime::Current()->RecordWriteField64(this, field_offset, old_value, true);
767 }
768 if (kVerifyFlags & kVerifyThis) {
769 VerifyObject(this);
770 }
771 uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
772 Atomic<int64_t>* atomic_addr = reinterpret_cast<Atomic<int64_t>*>(raw_addr);
773 return atomic_addr->CompareExchangeStrongSequentiallyConsistent(old_value, new_value);
774 }
775
776 template<class T, VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption,
777 bool kIsVolatile>
GetFieldObject(MemberOffset field_offset)778 inline T* Object::GetFieldObject(MemberOffset field_offset) {
779 if (kVerifyFlags & kVerifyThis) {
780 VerifyObject(this);
781 }
782 uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
783 HeapReference<T>* objref_addr = reinterpret_cast<HeapReference<T>*>(raw_addr);
784 T* result = ReadBarrier::Barrier<T, kReadBarrierOption>(this, field_offset, objref_addr);
785 if (kIsVolatile) {
786 // TODO: Refactor to use a SequentiallyConsistent load instead.
787 QuasiAtomic::ThreadFenceAcquire(); // Ensure visibility of operations preceding store.
788 }
789 if (kVerifyFlags & kVerifyReads) {
790 VerifyObject(result);
791 }
792 return result;
793 }
794
795 template<class T, VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
GetFieldObjectVolatile(MemberOffset field_offset)796 inline T* Object::GetFieldObjectVolatile(MemberOffset field_offset) {
797 return GetFieldObject<T, kVerifyFlags, kReadBarrierOption, true>(field_offset);
798 }
799
800 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags,
801 bool kIsVolatile>
SetFieldObjectWithoutWriteBarrier(MemberOffset field_offset,Object * new_value)802 inline void Object::SetFieldObjectWithoutWriteBarrier(MemberOffset field_offset,
803 Object* new_value) {
804 if (kCheckTransaction) {
805 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
806 }
807 if (kTransactionActive) {
808 mirror::Object* obj;
809 if (kIsVolatile) {
810 obj = GetFieldObjectVolatile<Object>(field_offset);
811 } else {
812 obj = GetFieldObject<Object>(field_offset);
813 }
814 Runtime::Current()->RecordWriteFieldReference(this, field_offset, obj, true);
815 }
816 if (kVerifyFlags & kVerifyThis) {
817 VerifyObject(this);
818 }
819 if (kVerifyFlags & kVerifyWrites) {
820 VerifyObject(new_value);
821 }
822 uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
823 HeapReference<Object>* objref_addr = reinterpret_cast<HeapReference<Object>*>(raw_addr);
824 if (kIsVolatile) {
825 // TODO: Refactor to use a SequentiallyConsistent store instead.
826 QuasiAtomic::ThreadFenceRelease(); // Ensure that prior accesses are visible before store.
827 objref_addr->Assign(new_value);
828 QuasiAtomic::ThreadFenceSequentiallyConsistent();
829 // Ensure this store occurs before any volatile loads.
830 } else {
831 objref_addr->Assign(new_value);
832 }
833 }
834
835 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags,
836 bool kIsVolatile>
SetFieldObject(MemberOffset field_offset,Object * new_value)837 inline void Object::SetFieldObject(MemberOffset field_offset, Object* new_value) {
838 SetFieldObjectWithoutWriteBarrier<kTransactionActive, kCheckTransaction, kVerifyFlags,
839 kIsVolatile>(field_offset, new_value);
840 if (new_value != nullptr) {
841 Runtime::Current()->GetHeap()->WriteBarrierField(this, field_offset, new_value);
842 // TODO: Check field assignment could theoretically cause thread suspension, TODO: fix this.
843 CheckFieldAssignment(field_offset, new_value);
844 }
845 }
846
847 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
SetFieldObjectVolatile(MemberOffset field_offset,Object * new_value)848 inline void Object::SetFieldObjectVolatile(MemberOffset field_offset, Object* new_value) {
849 SetFieldObject<kTransactionActive, kCheckTransaction, kVerifyFlags, true>(field_offset,
850 new_value);
851 }
852
853 template <VerifyObjectFlags kVerifyFlags>
GetFieldObjectReferenceAddr(MemberOffset field_offset)854 inline HeapReference<Object>* Object::GetFieldObjectReferenceAddr(MemberOffset field_offset) {
855 if (kVerifyFlags & kVerifyThis) {
856 VerifyObject(this);
857 }
858 return reinterpret_cast<HeapReference<Object>*>(reinterpret_cast<uint8_t*>(this) +
859 field_offset.Int32Value());
860 }
861
862 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
CasFieldWeakSequentiallyConsistentObject(MemberOffset field_offset,Object * old_value,Object * new_value)863 inline bool Object::CasFieldWeakSequentiallyConsistentObject(MemberOffset field_offset,
864 Object* old_value, Object* new_value) {
865 bool success = CasFieldWeakSequentiallyConsistentObjectWithoutWriteBarrier<
866 kTransactionActive, kCheckTransaction, kVerifyFlags>(field_offset, old_value, new_value);
867 if (success) {
868 Runtime::Current()->GetHeap()->WriteBarrierField(this, field_offset, new_value);
869 }
870 return success;
871 }
872
873 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
CasFieldWeakSequentiallyConsistentObjectWithoutWriteBarrier(MemberOffset field_offset,Object * old_value,Object * new_value)874 inline bool Object::CasFieldWeakSequentiallyConsistentObjectWithoutWriteBarrier(
875 MemberOffset field_offset, Object* old_value, Object* new_value) {
876 if (kCheckTransaction) {
877 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
878 }
879 if (kVerifyFlags & kVerifyThis) {
880 VerifyObject(this);
881 }
882 if (kVerifyFlags & kVerifyWrites) {
883 VerifyObject(new_value);
884 }
885 if (kVerifyFlags & kVerifyReads) {
886 VerifyObject(old_value);
887 }
888 if (kTransactionActive) {
889 Runtime::Current()->RecordWriteFieldReference(this, field_offset, old_value, true);
890 }
891 HeapReference<Object> old_ref(HeapReference<Object>::FromMirrorPtr(old_value));
892 HeapReference<Object> new_ref(HeapReference<Object>::FromMirrorPtr(new_value));
893 uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
894 Atomic<uint32_t>* atomic_addr = reinterpret_cast<Atomic<uint32_t>*>(raw_addr);
895
896 bool success = atomic_addr->CompareExchangeWeakSequentiallyConsistent(old_ref.reference_,
897 new_ref.reference_);
898 return success;
899 }
900
901 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
CasFieldStrongSequentiallyConsistentObject(MemberOffset field_offset,Object * old_value,Object * new_value)902 inline bool Object::CasFieldStrongSequentiallyConsistentObject(MemberOffset field_offset,
903 Object* old_value, Object* new_value) {
904 bool success = CasFieldStrongSequentiallyConsistentObjectWithoutWriteBarrier<
905 kTransactionActive, kCheckTransaction, kVerifyFlags>(field_offset, old_value, new_value);
906 if (success) {
907 Runtime::Current()->GetHeap()->WriteBarrierField(this, field_offset, new_value);
908 }
909 return success;
910 }
911
912 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
CasFieldStrongSequentiallyConsistentObjectWithoutWriteBarrier(MemberOffset field_offset,Object * old_value,Object * new_value)913 inline bool Object::CasFieldStrongSequentiallyConsistentObjectWithoutWriteBarrier(
914 MemberOffset field_offset, Object* old_value, 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 HeapReference<Object> old_ref(HeapReference<Object>::FromMirrorPtr(old_value));
931 HeapReference<Object> new_ref(HeapReference<Object>::FromMirrorPtr(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->CompareExchangeStrongSequentiallyConsistent(old_ref.reference_,
936 new_ref.reference_);
937 return success;
938 }
939
940 template<bool kVisitClass, bool kIsStatic, typename Visitor>
VisitFieldsReferences(uint32_t ref_offsets,const Visitor & visitor)941 inline void Object::VisitFieldsReferences(uint32_t ref_offsets, const Visitor& visitor) {
942 if (!kIsStatic && (ref_offsets != mirror::Class::kClassWalkSuper)) {
943 // Instance fields and not the slow-path.
944 if (kVisitClass) {
945 visitor(this, ClassOffset(), kIsStatic);
946 }
947 uint32_t field_offset = mirror::kObjectHeaderSize;
948 while (ref_offsets != 0) {
949 if ((ref_offsets & 1) != 0) {
950 visitor(this, MemberOffset(field_offset), kIsStatic);
951 }
952 ref_offsets >>= 1;
953 field_offset += sizeof(mirror::HeapReference<mirror::Object>);
954 }
955 } else {
956 // There is no reference offset bitmap. In the non-static case, walk up the class
957 // inheritance hierarchy and find reference offsets the hard way. In the static case, just
958 // consider this class.
959 for (mirror::Class* klass = kIsStatic ? AsClass() : GetClass(); klass != nullptr;
960 klass = kIsStatic ? nullptr : klass->GetSuperClass()) {
961 size_t num_reference_fields =
962 kIsStatic ? klass->NumReferenceStaticFields() : klass->NumReferenceInstanceFields();
963 if (num_reference_fields == 0u) {
964 continue;
965 }
966 // Presumably GC can happen when we are cross compiling, it should not cause performance
967 // problems to do pointer size logic.
968 MemberOffset field_offset = kIsStatic
969 ? klass->GetFirstReferenceStaticFieldOffset(
970 Runtime::Current()->GetClassLinker()->GetImagePointerSize())
971 : klass->GetFirstReferenceInstanceFieldOffset();
972 for (size_t i = 0; i < num_reference_fields; ++i) {
973 // TODO: Do a simpler check?
974 if (kVisitClass || field_offset.Uint32Value() != ClassOffset().Uint32Value()) {
975 visitor(this, field_offset, kIsStatic);
976 }
977 field_offset = MemberOffset(field_offset.Uint32Value() +
978 sizeof(mirror::HeapReference<mirror::Object>));
979 }
980 }
981 }
982 }
983
984 template<bool kVisitClass, typename Visitor>
VisitInstanceFieldsReferences(mirror::Class * klass,const Visitor & visitor)985 inline void Object::VisitInstanceFieldsReferences(mirror::Class* klass, const Visitor& visitor) {
986 VisitFieldsReferences<kVisitClass, false>(
987 klass->GetReferenceInstanceOffsets<kVerifyNone>(), visitor);
988 }
989
990 template<bool kVisitClass, typename Visitor>
VisitStaticFieldsReferences(mirror::Class * klass,const Visitor & visitor)991 inline void Object::VisitStaticFieldsReferences(mirror::Class* klass, const Visitor& visitor) {
992 DCHECK(!klass->IsTemp());
993 klass->VisitFieldsReferences<kVisitClass, true>(0, visitor);
994 }
995
996 template <const bool kVisitClass, VerifyObjectFlags kVerifyFlags, typename Visitor,
997 typename JavaLangRefVisitor>
VisitReferences(const Visitor & visitor,const JavaLangRefVisitor & ref_visitor)998 inline void Object::VisitReferences(const Visitor& visitor,
999 const JavaLangRefVisitor& ref_visitor) {
1000 mirror::Class* klass = GetClass<kVerifyFlags>();
1001 if (klass == Class::GetJavaLangClass()) {
1002 AsClass<kVerifyNone>()->VisitReferences<kVisitClass>(klass, visitor);
1003 } else if (klass->IsArrayClass() || klass->IsStringClass()) {
1004 if (klass->IsObjectArrayClass<kVerifyNone>()) {
1005 AsObjectArray<mirror::Object, kVerifyNone>()->VisitReferences<kVisitClass>(visitor);
1006 } else if (kVisitClass) {
1007 visitor(this, ClassOffset(), false);
1008 }
1009 } else {
1010 DCHECK(!klass->IsVariableSize());
1011 VisitInstanceFieldsReferences<kVisitClass>(klass, visitor);
1012 if (UNLIKELY(klass->IsTypeOfReferenceClass<kVerifyNone>())) {
1013 ref_visitor(klass, AsReference());
1014 }
1015 }
1016 }
1017 } // namespace mirror
1018 } // namespace art
1019
1020 #endif // ART_RUNTIME_MIRROR_OBJECT_INL_H_
1021