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.h"
41 #include "throwable.h"
42 #include "write_barrier-inl.h"
43
44 namespace art HIDDEN {
45 namespace mirror {
46
ClassSize(PointerSize pointer_size)47 inline uint32_t Object::ClassSize(PointerSize pointer_size) {
48 uint32_t vtable_entries = kVTableLength;
49 return Class::ComputeClassSize(true, vtable_entries, 0, 0, 0, 0, 0, 0, pointer_size);
50 }
51
52 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
GetClass()53 inline Class* Object::GetClass() {
54 return GetFieldObject<Class, kVerifyFlags, kReadBarrierOption>(ClassOffset());
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, RemoveThisFlags(kVerifyFlags)>(ClassOffset(),
65 new_klass);
66 }
67
68 template<VerifyObjectFlags kVerifyFlags>
SetLockWord(LockWord new_val,bool as_volatile)69 inline void Object::SetLockWord(LockWord new_val, bool as_volatile) {
70 // Force use of non-transactional mode and do not check.
71 if (as_volatile) {
72 SetField32Volatile<false, false, kVerifyFlags>(MonitorOffset(), new_val.GetValue());
73 } else {
74 SetField32<false, false, kVerifyFlags>(MonitorOffset(), new_val.GetValue());
75 }
76 }
77
GetLockOwnerThreadId()78 inline uint32_t Object::GetLockOwnerThreadId() {
79 return Monitor::GetLockOwnerThreadId(this);
80 }
81
MonitorEnter(Thread * self)82 inline ObjPtr<mirror::Object> Object::MonitorEnter(Thread* self) {
83 return Monitor::MonitorEnter(self, this, /*trylock=*/false);
84 }
85
MonitorTryEnter(Thread * self)86 inline ObjPtr<mirror::Object> Object::MonitorTryEnter(Thread* self) {
87 return Monitor::MonitorEnter(self, this, /*trylock=*/true);
88 }
89
MonitorExit(Thread * self)90 inline bool Object::MonitorExit(Thread* self) {
91 return Monitor::MonitorExit(self, this);
92 }
93
Notify(Thread * self)94 inline void Object::Notify(Thread* self) {
95 Monitor::Notify(self, this);
96 }
97
NotifyAll(Thread * self)98 inline void Object::NotifyAll(Thread* self) {
99 Monitor::NotifyAll(self, this);
100 }
101
Wait(Thread * self,int64_t ms,int32_t ns)102 inline void Object::Wait(Thread* self, int64_t ms, int32_t ns) {
103 Monitor::Wait(self, this, ms, ns, true, ThreadState::kTimedWaiting);
104 }
105
GetMarkBit()106 inline uint32_t Object::GetMarkBit() {
107 CHECK(gUseReadBarrier);
108 return GetLockWord(false).MarkBitState();
109 }
110
SetReadBarrierState(uint32_t rb_state)111 inline void Object::SetReadBarrierState(uint32_t rb_state) {
112 CHECK(kUseBakerReadBarrier);
113 DCHECK(ReadBarrier::IsValidReadBarrierState(rb_state)) << rb_state;
114 LockWord lw = GetLockWord(false);
115 lw.SetReadBarrierState(rb_state);
116 SetLockWord(lw, false);
117 }
118
AssertReadBarrierState()119 inline void Object::AssertReadBarrierState() const {
120 CHECK(kUseBakerReadBarrier);
121 Object* obj = const_cast<Object*>(this);
122 DCHECK_EQ(obj->GetReadBarrierState(), ReadBarrier::NonGrayState())
123 << "Bad Baker pointer: obj=" << obj << " rb_state" << obj->GetReadBarrierState();
124 }
125
126 template<VerifyObjectFlags kVerifyFlags>
VerifierInstanceOf(ObjPtr<Class> klass)127 inline bool Object::VerifierInstanceOf(ObjPtr<Class> klass) {
128 DCHECK(klass != nullptr);
129 DCHECK(GetClass<kVerifyFlags>() != nullptr);
130 return klass->IsInterface() || InstanceOf(klass);
131 }
132
133 template<VerifyObjectFlags kVerifyFlags>
InstanceOf(ObjPtr<Class> klass)134 inline bool Object::InstanceOf(ObjPtr<Class> klass) {
135 DCHECK(klass != nullptr);
136 DCHECK(GetClass<kVerifyNone>() != nullptr) << "this=" << this;
137 return klass->IsAssignableFrom(GetClass<kVerifyFlags>());
138 }
139
140 template<VerifyObjectFlags kVerifyFlags>
IsClass()141 inline bool Object::IsClass() {
142 // OK to look at from-space copies since java.lang.Class.class is non-moveable
143 // (even when running without boot image, see ClassLinker::InitWithoutImage())
144 // and we're reading constant references for comparison only. See ReadBarrierOption.
145 ObjPtr<Class> klass = GetClass<kVerifyFlags, kWithoutReadBarrier>();
146 ObjPtr<Class> java_lang_Class = klass->GetClass<kVerifyFlags, kWithoutReadBarrier>();
147 return klass == java_lang_Class;
148 }
149
150 template<VerifyObjectFlags kVerifyFlags>
AsClass()151 inline ObjPtr<Class> Object::AsClass() {
152 DCHECK((IsClass<kVerifyFlags>()));
153 return ObjPtr<Class>::DownCast(this);
154 }
155
156 template<VerifyObjectFlags kVerifyFlags>
IsObjectArray()157 inline bool Object::IsObjectArray() {
158 // We do not need a read barrier here as the primitive type is constant,
159 // both from-space and to-space component type classes shall yield the same result.
160 constexpr VerifyObjectFlags kNewFlags = RemoveThisFlags(kVerifyFlags);
161 return IsArrayInstance<kVerifyFlags>() &&
162 !GetClass<kNewFlags, kWithoutReadBarrier>()->
163 template GetComponentType<kNewFlags, kWithoutReadBarrier>()->IsPrimitive();
164 }
165
166 template<class T, VerifyObjectFlags kVerifyFlags>
AsObjectArray()167 inline ObjPtr<ObjectArray<T>> Object::AsObjectArray() {
168 DCHECK((IsObjectArray<kVerifyFlags>()));
169 return ObjPtr<ObjectArray<T>>::DownCast(this);
170 }
171
172 template<VerifyObjectFlags kVerifyFlags>
IsArrayInstance()173 inline bool Object::IsArrayInstance() {
174 // We do not need a read barrier here, both from-space and to-space version of the class
175 // shall return the same result from IsArrayClass().
176 return GetClass<kVerifyFlags, kWithoutReadBarrier>()->template IsArrayClass<kVerifyFlags>();
177 }
178
179 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
IsReferenceInstance()180 inline bool Object::IsReferenceInstance() {
181 return GetClass<kVerifyFlags, kReadBarrierOption>()->IsTypeOfReferenceClass();
182 }
183
184 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
AsReference()185 inline ObjPtr<Reference> Object::AsReference() {
186 DCHECK((IsReferenceInstance<kVerifyFlags, kReadBarrierOption>()));
187 return ObjPtr<Reference>::DownCast(this);
188 }
189
190 template<VerifyObjectFlags kVerifyFlags>
AsArray()191 inline ObjPtr<Array> Object::AsArray() {
192 DCHECK((IsArrayInstance<kVerifyFlags>()));
193 return ObjPtr<Array>::DownCast(this);
194 }
195
196 template<VerifyObjectFlags kVerifyFlags, Primitive::Type kType>
IsSpecificPrimitiveArray()197 ALWAYS_INLINE bool Object::IsSpecificPrimitiveArray() {
198 // We do not need a read barrier here as the primitive type is constant, both from-space
199 // and to-space component type classes shall yield the same result. See ReadBarrierOption.
200 const ObjPtr<Class> klass = GetClass<kVerifyFlags, kWithoutReadBarrier>();
201 constexpr VerifyObjectFlags kNewFlags = RemoveThisFlags(kVerifyFlags);
202 const ObjPtr<Class> component_type = klass->GetComponentType<kNewFlags, kWithoutReadBarrier>();
203 return component_type != nullptr &&
204 component_type->GetPrimitiveType<kNewFlags>() == kType;
205 }
206
207 template<VerifyObjectFlags kVerifyFlags>
IsBooleanArray()208 inline bool Object::IsBooleanArray() {
209 return IsSpecificPrimitiveArray<kVerifyFlags, Primitive::kPrimBoolean>();
210 }
211
212 template<VerifyObjectFlags kVerifyFlags>
AsBooleanArray()213 inline ObjPtr<BooleanArray> Object::AsBooleanArray() {
214 DCHECK(IsBooleanArray<kVerifyFlags>());
215 return ObjPtr<BooleanArray>::DownCast(this);
216 }
217
218 template<VerifyObjectFlags kVerifyFlags>
IsByteArray()219 inline bool Object::IsByteArray() {
220 return IsSpecificPrimitiveArray<kVerifyFlags, Primitive::kPrimByte>();
221 }
222
223 template<VerifyObjectFlags kVerifyFlags>
AsByteArray()224 inline ObjPtr<ByteArray> Object::AsByteArray() {
225 DCHECK(IsByteArray<kVerifyFlags>());
226 return ObjPtr<ByteArray>::DownCast(this);
227 }
228
229 template<VerifyObjectFlags kVerifyFlags>
IsCharArray()230 inline bool Object::IsCharArray() {
231 return IsSpecificPrimitiveArray<kVerifyFlags, Primitive::kPrimChar>();
232 }
233
234 template<VerifyObjectFlags kVerifyFlags>
AsCharArray()235 inline ObjPtr<CharArray> Object::AsCharArray() {
236 DCHECK(IsCharArray<kVerifyFlags>());
237 return ObjPtr<CharArray>::DownCast(this);
238 }
239
240 template<VerifyObjectFlags kVerifyFlags>
IsShortArray()241 inline bool Object::IsShortArray() {
242 return IsSpecificPrimitiveArray<kVerifyFlags, Primitive::kPrimShort>();
243 }
244
245 template<VerifyObjectFlags kVerifyFlags>
AsShortArray()246 inline ObjPtr<ShortArray> Object::AsShortArray() {
247 DCHECK(IsShortArray<kVerifyFlags>());
248 return ObjPtr<ShortArray>::DownCast(this);
249 }
250
251 template<VerifyObjectFlags kVerifyFlags>
IsIntArray()252 inline bool Object::IsIntArray() {
253 return IsSpecificPrimitiveArray<kVerifyFlags, Primitive::kPrimInt>();
254 }
255
256 template<VerifyObjectFlags kVerifyFlags>
AsIntArrayUnchecked()257 inline ObjPtr<IntArray> Object::AsIntArrayUnchecked() {
258 return ObjPtr<IntArray>::DownCast(this);
259 }
260 template<VerifyObjectFlags kVerifyFlags>
AsIntArray()261 inline ObjPtr<IntArray> Object::AsIntArray() {
262 DCHECK((IsIntArray<kVerifyFlags>()));
263 return AsIntArrayUnchecked<kVerifyFlags>();
264 }
265
266 template<VerifyObjectFlags kVerifyFlags>
IsLongArray()267 inline bool Object::IsLongArray() {
268 return IsSpecificPrimitiveArray<kVerifyFlags, Primitive::kPrimLong>();
269 }
270
271 template<VerifyObjectFlags kVerifyFlags>
AsLongArrayUnchecked()272 inline ObjPtr<LongArray> Object::AsLongArrayUnchecked() {
273 return ObjPtr<LongArray>::DownCast(this);
274 }
275 template<VerifyObjectFlags kVerifyFlags>
AsLongArray()276 inline ObjPtr<LongArray> Object::AsLongArray() {
277 DCHECK((IsLongArray<kVerifyFlags>()));
278 return AsLongArrayUnchecked<kVerifyFlags>();
279 }
280
281 template<VerifyObjectFlags kVerifyFlags>
IsFloatArray()282 inline bool Object::IsFloatArray() {
283 return IsSpecificPrimitiveArray<kVerifyFlags, Primitive::kPrimFloat>();
284 }
285
286 template<VerifyObjectFlags kVerifyFlags>
AsFloatArray()287 inline ObjPtr<FloatArray> Object::AsFloatArray() {
288 DCHECK(IsFloatArray<kVerifyFlags>());
289 return ObjPtr<FloatArray>::DownCast(this);
290 }
291
292 template<VerifyObjectFlags kVerifyFlags>
IsDoubleArray()293 inline bool Object::IsDoubleArray() {
294 return IsSpecificPrimitiveArray<kVerifyFlags, Primitive::kPrimDouble>();
295 }
296
297 template<VerifyObjectFlags kVerifyFlags>
AsDoubleArray()298 inline ObjPtr<DoubleArray> Object::AsDoubleArray() {
299 DCHECK(IsDoubleArray<kVerifyFlags>());
300 return ObjPtr<DoubleArray>::DownCast(this);
301 }
302
303 template<VerifyObjectFlags kVerifyFlags>
IsString()304 inline bool Object::IsString() {
305 // No read barrier is needed for reading a constant primitive field through
306 // constant reference field. See ReadBarrierOption.
307 return GetClass<kVerifyFlags, kWithoutReadBarrier>()->IsStringClass();
308 }
309
310 template<VerifyObjectFlags kVerifyFlags>
AsString()311 inline ObjPtr<String> Object::AsString() {
312 DCHECK((IsString<kVerifyFlags>()));
313 return ObjPtr<String>::DownCast(this);
314 }
315
316 template<VerifyObjectFlags kVerifyFlags>
AsThrowable()317 inline ObjPtr<Throwable> Object::AsThrowable() {
318 DCHECK(GetClass<kVerifyFlags>()->IsThrowableClass());
319 return ObjPtr<Throwable>::DownCast(this);
320 }
321
322 template<VerifyObjectFlags kVerifyFlags>
IsWeakReferenceInstance()323 inline bool Object::IsWeakReferenceInstance() {
324 return GetClass<kVerifyFlags>()->IsWeakReferenceClass();
325 }
326
327 template<VerifyObjectFlags kVerifyFlags>
IsSoftReferenceInstance()328 inline bool Object::IsSoftReferenceInstance() {
329 return GetClass<kVerifyFlags>()->IsSoftReferenceClass();
330 }
331
332 template<VerifyObjectFlags kVerifyFlags>
IsFinalizerReferenceInstance()333 inline bool Object::IsFinalizerReferenceInstance() {
334 return GetClass<kVerifyFlags>()->IsFinalizerReferenceClass();
335 }
336
337 template<VerifyObjectFlags kVerifyFlags>
AsFinalizerReference()338 inline ObjPtr<FinalizerReference> Object::AsFinalizerReference() {
339 DCHECK(IsFinalizerReferenceInstance<kVerifyFlags>());
340 return ObjPtr<FinalizerReference>::DownCast(this);
341 }
342
343 template<VerifyObjectFlags kVerifyFlags>
IsPhantomReferenceInstance()344 inline bool Object::IsPhantomReferenceInstance() {
345 return GetClass<kVerifyFlags>()->IsPhantomReferenceClass();
346 }
347
348 // TODO: optimize this by using class_flags_ to determine type
349 template<VerifyObjectFlags kVerifyFlags>
SizeOf()350 inline size_t Object::SizeOf() {
351 // Read barrier is never required for SizeOf since objects sizes are constant. Reading from-space
352 // values is OK because of that.
353 size_t result;
354 constexpr VerifyObjectFlags kNewFlags = RemoveThisFlags(kVerifyFlags);
355 if (IsArrayInstance<kVerifyFlags>()) {
356 result = AsArray<kNewFlags>()->template SizeOf<kNewFlags>();
357 } else if (IsClass<kNewFlags>()) {
358 result = AsClass<kNewFlags>()->template SizeOf<kNewFlags>();
359 } else if (IsString<kNewFlags>()) {
360 result = AsString<kNewFlags>()->template SizeOf<kNewFlags>();
361 } else {
362 result = GetClass<kNewFlags, kWithoutReadBarrier>()->template GetObjectSize<kNewFlags>();
363 }
364 DCHECK_GE(result, sizeof(Object)) << " class="
365 // Note: Class::PrettyClass() is reading constant reference fields to get to constant
366 // primitive fields and safely avoids read barriers, so it is safe to call on a Class
367 // reference read without read barrier from a constant reference field.
368 // See ReadBarrierOption. And, for correctness, we actually have to avoid the read
369 // barrier here if Object::SizeOf() is called on a from-space reference.
370 << GetClass<kNewFlags, kWithoutReadBarrier>()->PrettyClass();
371 return result;
372 }
373
374 template<VerifyObjectFlags kVerifyFlags, bool kIsVolatile>
GetFieldByte(MemberOffset field_offset)375 inline int8_t Object::GetFieldByte(MemberOffset field_offset) {
376 Verify<kVerifyFlags>();
377 return GetFieldPrimitive<int8_t, kIsVolatile>(field_offset);
378 }
379
380 template<VerifyObjectFlags kVerifyFlags>
GetFieldBooleanVolatile(MemberOffset field_offset)381 inline uint8_t Object::GetFieldBooleanVolatile(MemberOffset field_offset) {
382 return GetFieldBoolean<kVerifyFlags, true>(field_offset);
383 }
384
385 template<VerifyObjectFlags kVerifyFlags>
GetFieldByteVolatile(MemberOffset field_offset)386 inline int8_t Object::GetFieldByteVolatile(MemberOffset field_offset) {
387 return GetFieldByte<kVerifyFlags, true>(field_offset);
388 }
389
390 template<bool kTransactionActive,
391 bool kCheckTransaction,
392 VerifyObjectFlags kVerifyFlags,
393 bool kIsVolatile>
SetFieldBoolean(MemberOffset field_offset,uint8_t new_value)394 inline void Object::SetFieldBoolean(MemberOffset field_offset, uint8_t new_value) {
395 VerifyTransaction<kTransactionActive, kCheckTransaction>();
396 if (kTransactionActive) {
397 Runtime::Current()->GetClassLinker()->RecordWriteFieldBoolean(
398 this, field_offset, GetFieldBoolean<kVerifyFlags, kIsVolatile>(field_offset), kIsVolatile);
399 }
400 Verify<kVerifyFlags>();
401 SetFieldPrimitive<uint8_t, kIsVolatile>(field_offset, new_value);
402 }
403
404 template<bool kTransactionActive,
405 bool kCheckTransaction,
406 VerifyObjectFlags kVerifyFlags,
407 bool kIsVolatile>
SetFieldByte(MemberOffset field_offset,int8_t new_value)408 inline void Object::SetFieldByte(MemberOffset field_offset, int8_t new_value) {
409 VerifyTransaction<kTransactionActive, kCheckTransaction>();
410 if (kTransactionActive) {
411 Runtime::Current()->GetClassLinker()->RecordWriteFieldByte(
412 this, field_offset, GetFieldByte<kVerifyFlags, kIsVolatile>(field_offset), kIsVolatile);
413 }
414 Verify<kVerifyFlags>();
415 SetFieldPrimitive<int8_t, kIsVolatile>(field_offset, new_value);
416 }
417
418 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
SetFieldBooleanVolatile(MemberOffset field_offset,uint8_t new_value)419 inline void Object::SetFieldBooleanVolatile(MemberOffset field_offset, uint8_t new_value) {
420 return SetFieldBoolean<kTransactionActive, kCheckTransaction, kVerifyFlags, true>(
421 field_offset, new_value);
422 }
423
424 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
SetFieldByteVolatile(MemberOffset field_offset,int8_t new_value)425 inline void Object::SetFieldByteVolatile(MemberOffset field_offset, int8_t new_value) {
426 return SetFieldByte<kTransactionActive, kCheckTransaction, kVerifyFlags, true>(
427 field_offset, new_value);
428 }
429
430 template<VerifyObjectFlags kVerifyFlags, bool kIsVolatile>
GetFieldChar(MemberOffset field_offset)431 inline uint16_t Object::GetFieldChar(MemberOffset field_offset) {
432 Verify<kVerifyFlags>();
433 return GetFieldPrimitive<uint16_t, kIsVolatile>(field_offset);
434 }
435
436 template<VerifyObjectFlags kVerifyFlags, bool kIsVolatile>
GetFieldShort(MemberOffset field_offset)437 inline int16_t Object::GetFieldShort(MemberOffset field_offset) {
438 Verify<kVerifyFlags>();
439 return GetFieldPrimitive<int16_t, kIsVolatile>(field_offset);
440 }
441
442 template<VerifyObjectFlags kVerifyFlags>
GetFieldCharVolatile(MemberOffset field_offset)443 inline uint16_t Object::GetFieldCharVolatile(MemberOffset field_offset) {
444 return GetFieldChar<kVerifyFlags, true>(field_offset);
445 }
446
447 template<VerifyObjectFlags kVerifyFlags>
GetFieldShortVolatile(MemberOffset field_offset)448 inline int16_t Object::GetFieldShortVolatile(MemberOffset field_offset) {
449 return GetFieldShort<kVerifyFlags, true>(field_offset);
450 }
451
452 template<bool kTransactionActive,
453 bool kCheckTransaction,
454 VerifyObjectFlags kVerifyFlags,
455 bool kIsVolatile>
SetFieldChar(MemberOffset field_offset,uint16_t new_value)456 inline void Object::SetFieldChar(MemberOffset field_offset, uint16_t new_value) {
457 VerifyTransaction<kTransactionActive, kCheckTransaction>();
458 if (kTransactionActive) {
459 Runtime::Current()->GetClassLinker()->RecordWriteFieldChar(
460 this, field_offset, GetFieldChar<kVerifyFlags, kIsVolatile>(field_offset), kIsVolatile);
461 }
462 Verify<kVerifyFlags>();
463 SetFieldPrimitive<uint16_t, kIsVolatile>(field_offset, new_value);
464 }
465
466 template<bool kTransactionActive,
467 bool kCheckTransaction,
468 VerifyObjectFlags kVerifyFlags,
469 bool kIsVolatile>
SetFieldShort(MemberOffset field_offset,int16_t new_value)470 inline void Object::SetFieldShort(MemberOffset field_offset, int16_t new_value) {
471 VerifyTransaction<kTransactionActive, kCheckTransaction>();
472 if (kTransactionActive) {
473 Runtime::Current()->GetClassLinker()->RecordWriteFieldChar(
474 this, field_offset, GetFieldShort<kVerifyFlags, kIsVolatile>(field_offset), kIsVolatile);
475 }
476 Verify<kVerifyFlags>();
477 SetFieldPrimitive<int16_t, kIsVolatile>(field_offset, new_value);
478 }
479
480 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
SetFieldCharVolatile(MemberOffset field_offset,uint16_t new_value)481 inline void Object::SetFieldCharVolatile(MemberOffset field_offset, uint16_t new_value) {
482 return SetFieldChar<kTransactionActive, kCheckTransaction, kVerifyFlags, true>(
483 field_offset, new_value);
484 }
485
486 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
SetFieldShortVolatile(MemberOffset field_offset,int16_t new_value)487 inline void Object::SetFieldShortVolatile(MemberOffset field_offset, int16_t new_value) {
488 return SetFieldShort<kTransactionActive, kCheckTransaction, kVerifyFlags, true>(
489 field_offset, new_value);
490 }
491
492 template<bool kTransactionActive,
493 bool kCheckTransaction,
494 VerifyObjectFlags kVerifyFlags,
495 bool kIsVolatile>
SetField32(MemberOffset field_offset,int32_t new_value)496 inline void Object::SetField32(MemberOffset field_offset, int32_t new_value) {
497 VerifyTransaction<kTransactionActive, kCheckTransaction>();
498 if (kTransactionActive) {
499 Runtime::Current()->GetClassLinker()->RecordWriteField32(
500 this, field_offset, GetField32<kVerifyFlags, kIsVolatile>(field_offset), kIsVolatile);
501 }
502 Verify<kVerifyFlags>();
503 SetFieldPrimitive<int32_t, kIsVolatile>(field_offset, new_value);
504 }
505
506 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
SetField32Volatile(MemberOffset field_offset,int32_t new_value)507 inline void Object::SetField32Volatile(MemberOffset field_offset, int32_t new_value) {
508 SetField32<kTransactionActive, kCheckTransaction, kVerifyFlags, true>(field_offset, new_value);
509 }
510
511 template<bool kCheckTransaction, VerifyObjectFlags kVerifyFlags, bool kIsVolatile>
SetField32Transaction(MemberOffset field_offset,int32_t new_value)512 inline void Object::SetField32Transaction(MemberOffset field_offset, int32_t new_value) {
513 if (Runtime::Current()->IsActiveTransaction()) {
514 SetField32<true, kCheckTransaction, kVerifyFlags, kIsVolatile>(field_offset, new_value);
515 } else {
516 SetField32<false, kCheckTransaction, kVerifyFlags, kIsVolatile>(field_offset, new_value);
517 }
518 }
519
520 template<bool kTransactionActive,
521 bool kCheckTransaction,
522 VerifyObjectFlags kVerifyFlags,
523 bool kIsVolatile>
SetField64(MemberOffset field_offset,int64_t new_value)524 inline void Object::SetField64(MemberOffset field_offset, int64_t new_value) {
525 VerifyTransaction<kTransactionActive, kCheckTransaction>();
526 if (kTransactionActive) {
527 Runtime::Current()->GetClassLinker()->RecordWriteField64(
528 this, field_offset, GetField64<kVerifyFlags, kIsVolatile>(field_offset), kIsVolatile);
529 }
530 Verify<kVerifyFlags>();
531 SetFieldPrimitive<int64_t, kIsVolatile>(field_offset, new_value);
532 }
533
534 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
SetField64Volatile(MemberOffset field_offset,int64_t new_value)535 inline void Object::SetField64Volatile(MemberOffset field_offset, int64_t new_value) {
536 return SetField64<kTransactionActive, kCheckTransaction, kVerifyFlags, true>(field_offset,
537 new_value);
538 }
539
540 template<bool kCheckTransaction, VerifyObjectFlags kVerifyFlags, bool kIsVolatile>
SetField64Transaction(MemberOffset field_offset,int32_t new_value)541 inline void Object::SetField64Transaction(MemberOffset field_offset, int32_t new_value) {
542 if (Runtime::Current()->IsActiveTransaction()) {
543 SetField64<true, kCheckTransaction, kVerifyFlags, kIsVolatile>(field_offset, new_value);
544 } else {
545 SetField64<false, kCheckTransaction, kVerifyFlags, kIsVolatile>(field_offset, new_value);
546 }
547 }
548
549 template<typename kSize>
GetFieldAcquire(MemberOffset field_offset)550 inline kSize Object::GetFieldAcquire(MemberOffset field_offset) {
551 const uint8_t* raw_addr = reinterpret_cast<const uint8_t*>(this) + field_offset.Int32Value();
552 const kSize* addr = reinterpret_cast<const kSize*>(raw_addr);
553 return reinterpret_cast<const Atomic<kSize>*>(addr)->load(std::memory_order_acquire);
554 }
555
556 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
CasFieldWeakSequentiallyConsistent64(MemberOffset field_offset,int64_t old_value,int64_t new_value)557 inline bool Object::CasFieldWeakSequentiallyConsistent64(MemberOffset field_offset,
558 int64_t old_value,
559 int64_t new_value) {
560 VerifyTransaction<kTransactionActive, kCheckTransaction>();
561 Verify<kVerifyFlags>();
562 uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
563 Atomic<int64_t>* atomic_addr = reinterpret_cast<Atomic<int64_t>*>(raw_addr);
564 bool success = atomic_addr->CompareAndSetWeakSequentiallyConsistent(old_value, new_value);
565 if (kTransactionActive && success) {
566 Runtime::Current()->GetClassLinker()->RecordWriteField64(
567 this, field_offset, old_value, /*is_volatile=*/ true);
568 }
569 return success;
570 }
571
572 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
CasFieldStrongSequentiallyConsistent64(MemberOffset field_offset,int64_t old_value,int64_t new_value)573 inline bool Object::CasFieldStrongSequentiallyConsistent64(MemberOffset field_offset,
574 int64_t old_value,
575 int64_t new_value) {
576 VerifyTransaction<kTransactionActive, kCheckTransaction>();
577 Verify<kVerifyFlags>();
578 uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
579 Atomic<int64_t>* atomic_addr = reinterpret_cast<Atomic<int64_t>*>(raw_addr);
580 bool success = atomic_addr->CompareAndSetStrongSequentiallyConsistent(old_value, new_value);
581 if (kTransactionActive && success) {
582 Runtime::Current()->GetClassLinker()->RecordWriteField64(
583 this, field_offset, old_value, /*is_volatile=*/ true);
584 }
585 return success;
586 }
587
588 template <bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
CaeFieldStrongSequentiallyConsistent64(MemberOffset field_offset,int64_t old_value,int64_t new_value)589 inline int64_t Object::CaeFieldStrongSequentiallyConsistent64(MemberOffset field_offset,
590 int64_t old_value,
591 int64_t new_value) {
592 VerifyTransaction<kTransactionActive, kCheckTransaction>();
593 Verify<kVerifyFlags>();
594 uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
595 Atomic<int64_t>* atomic_addr = reinterpret_cast<Atomic<int64_t>*>(raw_addr);
596 int64_t found_value =
597 atomic_addr->CompareAndExchangeStrongSequentiallyConsistent(old_value, new_value);
598 if (kTransactionActive && found_value == old_value) {
599 Runtime::Current()->GetClassLinker()->RecordWriteField64(
600 this, field_offset, old_value, /*is_volatile=*/true);
601 }
602 return found_value;
603 }
604
605 /*
606 * Returns a pointer to an object representing what the field points to, not an
607 * object representing the field.
608 */
609 template<class T,
610 VerifyObjectFlags kVerifyFlags,
611 ReadBarrierOption kReadBarrierOption,
612 bool kIsVolatile>
GetFieldObject(MemberOffset field_offset)613 inline T* Object::GetFieldObject(MemberOffset field_offset) {
614 Verify<kVerifyFlags>();
615 uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
616 HeapReference<T>* objref_addr = reinterpret_cast<HeapReference<T>*>(raw_addr);
617 T* result = ReadBarrier::Barrier<T, kIsVolatile, kReadBarrierOption>(
618 this,
619 field_offset,
620 objref_addr);
621 VerifyRead<kVerifyFlags>(result);
622 return result;
623 }
624
625 template<class T, VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
GetFieldObjectVolatile(MemberOffset field_offset)626 inline T* Object::GetFieldObjectVolatile(MemberOffset field_offset) {
627 return GetFieldObject<T, kVerifyFlags, kReadBarrierOption, true>(field_offset);
628 }
629
630 template<bool kTransactionActive,
631 bool kCheckTransaction,
632 VerifyObjectFlags kVerifyFlags,
633 bool kIsVolatile>
SetFieldObjectWithoutWriteBarrier(MemberOffset field_offset,ObjPtr<Object> new_value)634 inline void Object::SetFieldObjectWithoutWriteBarrier(MemberOffset field_offset,
635 ObjPtr<Object> new_value) {
636 VerifyTransaction<kTransactionActive, kCheckTransaction>();
637 if (kTransactionActive) {
638 ObjPtr<Object> old_value =
639 GetFieldObject<Object, kVerifyFlags, kWithReadBarrier, kIsVolatile>(field_offset);
640 Runtime::Current()->GetClassLinker()->RecordWriteFieldReference(
641 this, field_offset, old_value, kIsVolatile);
642 }
643 Verify<kVerifyFlags>();
644 VerifyWrite<kVerifyFlags>(new_value);
645 uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
646 HeapReference<Object>* objref_addr = reinterpret_cast<HeapReference<Object>*>(raw_addr);
647 objref_addr->Assign<kIsVolatile>(new_value.Ptr());
648 }
649
650 template<bool kTransactionActive,
651 bool kCheckTransaction,
652 VerifyObjectFlags kVerifyFlags,
653 bool kIsVolatile>
SetFieldObject(MemberOffset field_offset,ObjPtr<Object> new_value)654 inline void Object::SetFieldObject(MemberOffset field_offset, ObjPtr<Object> new_value) {
655 SetFieldObjectWithoutWriteBarrier<kTransactionActive, kCheckTransaction, kVerifyFlags,
656 kIsVolatile>(field_offset, new_value);
657 if (new_value != nullptr) {
658 WriteBarrier::ForFieldWrite<WriteBarrier::kWithoutNullCheck>(this, field_offset, new_value);
659 // TODO: Check field assignment could theoretically cause thread suspension, TODO: fix this.
660 CheckFieldAssignment(field_offset, new_value);
661 }
662 }
663
664 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
SetFieldObjectVolatile(MemberOffset field_offset,ObjPtr<Object> new_value)665 inline void Object::SetFieldObjectVolatile(MemberOffset field_offset, ObjPtr<Object> new_value) {
666 SetFieldObject<kTransactionActive, kCheckTransaction, kVerifyFlags, true>(field_offset,
667 new_value);
668 }
669
670 template<bool kCheckTransaction, VerifyObjectFlags kVerifyFlags, bool kIsVolatile>
SetFieldObjectTransaction(MemberOffset field_offset,ObjPtr<Object> new_value)671 inline void Object::SetFieldObjectTransaction(MemberOffset field_offset, ObjPtr<Object> new_value) {
672 if (Runtime::Current()->IsActiveTransaction()) {
673 SetFieldObject<true, kCheckTransaction, kVerifyFlags, kIsVolatile>(field_offset, new_value);
674 } else {
675 SetFieldObject<false, kCheckTransaction, kVerifyFlags, kIsVolatile>(field_offset, new_value);
676 }
677 }
678
679 template <VerifyObjectFlags kVerifyFlags>
GetFieldObjectReferenceAddr(MemberOffset field_offset)680 inline HeapReference<Object>* Object::GetFieldObjectReferenceAddr(MemberOffset field_offset) {
681 Verify<kVerifyFlags>();
682 return reinterpret_cast<HeapReference<Object>*>(reinterpret_cast<uint8_t*>(this) +
683 field_offset.Int32Value());
684 }
685
686 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
CasFieldObjectWithoutWriteBarrier(MemberOffset field_offset,ObjPtr<Object> old_value,ObjPtr<Object> new_value,CASMode mode,std::memory_order memory_order)687 inline bool Object::CasFieldObjectWithoutWriteBarrier(MemberOffset field_offset,
688 ObjPtr<Object> old_value,
689 ObjPtr<Object> new_value,
690 CASMode mode,
691 std::memory_order memory_order) {
692 VerifyTransaction<kTransactionActive, kCheckTransaction>();
693 VerifyCAS<kVerifyFlags>(new_value, old_value);
694 uint32_t old_ref(PtrCompression<kPoisonHeapReferences, Object>::Compress(old_value));
695 uint32_t new_ref(PtrCompression<kPoisonHeapReferences, Object>::Compress(new_value));
696 uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
697 Atomic<uint32_t>* atomic_addr = reinterpret_cast<Atomic<uint32_t>*>(raw_addr);
698 bool success = atomic_addr->CompareAndSet(old_ref, new_ref, mode, memory_order);
699 if (kTransactionActive && success) {
700 Runtime::Current()->GetClassLinker()->RecordWriteFieldReference(
701 this, field_offset, old_value, /*is_volatile=*/ true);
702 }
703 return success;
704 }
705
706 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
CasFieldObject(MemberOffset field_offset,ObjPtr<Object> old_value,ObjPtr<Object> new_value,CASMode mode,std::memory_order memory_order)707 inline bool Object::CasFieldObject(MemberOffset field_offset,
708 ObjPtr<Object> old_value,
709 ObjPtr<Object> new_value,
710 CASMode mode,
711 std::memory_order memory_order) {
712 bool success = CasFieldObjectWithoutWriteBarrier<
713 kTransactionActive, kCheckTransaction, kVerifyFlags>(field_offset,
714 old_value,
715 new_value,
716 mode,
717 memory_order);
718 if (success) {
719 WriteBarrier::ForFieldWrite(this, field_offset, new_value);
720 }
721 return success;
722 }
723
724 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
CompareAndExchangeFieldObject(MemberOffset field_offset,ObjPtr<Object> old_value,ObjPtr<Object> new_value)725 inline ObjPtr<Object> Object::CompareAndExchangeFieldObject(MemberOffset field_offset,
726 ObjPtr<Object> old_value,
727 ObjPtr<Object> new_value) {
728 VerifyTransaction<kTransactionActive, kCheckTransaction>();
729 VerifyCAS<kVerifyFlags>(new_value, old_value);
730 uint32_t old_ref(PtrCompression<kPoisonHeapReferences, Object>::Compress(old_value));
731 uint32_t new_ref(PtrCompression<kPoisonHeapReferences, Object>::Compress(new_value));
732 uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
733 Atomic<uint32_t>* atomic_addr = reinterpret_cast<Atomic<uint32_t>*>(raw_addr);
734 bool success = atomic_addr->compare_exchange_strong(old_ref, new_ref, std::memory_order_seq_cst);
735 ObjPtr<Object> witness_value(PtrCompression<kPoisonHeapReferences, Object>::Decompress(old_ref));
736 if (kIsDebugBuild) {
737 // Ensure caller has done read barrier on the reference field so it's in the to-space.
738 ReadBarrier::AssertToSpaceInvariant(witness_value.Ptr());
739 }
740 if (success) {
741 if (kTransactionActive) {
742 Runtime::Current()->GetClassLinker()->RecordWriteFieldReference(
743 this, field_offset, witness_value, /*is_volatile=*/ true);
744 }
745 WriteBarrier::ForFieldWrite(this, field_offset, new_value);
746 }
747 VerifyRead<kVerifyFlags>(witness_value);
748 return witness_value;
749 }
750
751 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
ExchangeFieldObject(MemberOffset field_offset,ObjPtr<Object> new_value)752 inline ObjPtr<Object> Object::ExchangeFieldObject(MemberOffset field_offset,
753 ObjPtr<Object> new_value) {
754 VerifyTransaction<kTransactionActive, kCheckTransaction>();
755 VerifyCAS<kVerifyFlags>(new_value, /*old_value=*/ nullptr);
756
757 uint32_t new_ref(PtrCompression<kPoisonHeapReferences, Object>::Compress(new_value));
758 uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
759 Atomic<uint32_t>* atomic_addr = reinterpret_cast<Atomic<uint32_t>*>(raw_addr);
760 uint32_t old_ref = atomic_addr->exchange(new_ref, std::memory_order_seq_cst);
761 ObjPtr<Object> old_value(PtrCompression<kPoisonHeapReferences, Object>::Decompress(old_ref));
762 if (kIsDebugBuild) {
763 // Ensure caller has done read barrier on the reference field so it's in the to-space.
764 ReadBarrier::AssertToSpaceInvariant(old_value.Ptr());
765 }
766 if (kTransactionActive) {
767 Runtime::Current()->GetClassLinker()->RecordWriteFieldReference(
768 this, field_offset, old_value, /*is_volatile=*/ true);
769 }
770 WriteBarrier::ForFieldWrite(this, field_offset, new_value);
771 VerifyRead<kVerifyFlags>(old_value);
772 return old_value;
773 }
774
775 template<typename T, VerifyObjectFlags kVerifyFlags>
GetPrimitiveFieldViaAccessor(MemberOffset field_offset,Accessor<T> * accessor)776 inline void Object::GetPrimitiveFieldViaAccessor(MemberOffset field_offset, Accessor<T>* accessor) {
777 Verify<kVerifyFlags>();
778 uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
779 T* addr = reinterpret_cast<T*>(raw_addr);
780 accessor->Access(addr);
781 }
782
783 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
UpdateFieldBooleanViaAccessor(MemberOffset field_offset,Accessor<uint8_t> * accessor)784 inline void Object::UpdateFieldBooleanViaAccessor(MemberOffset field_offset,
785 Accessor<uint8_t>* accessor) {
786 VerifyTransaction<kTransactionActive, kCheckTransaction>();
787 if (kTransactionActive) {
788 static const bool kIsVolatile = true;
789 uint8_t old_value = GetFieldBoolean<kVerifyFlags, kIsVolatile>(field_offset);
790 Runtime::Current()->GetClassLinker()->RecordWriteFieldBoolean(
791 this, field_offset, old_value, kIsVolatile);
792 }
793 Verify<kVerifyFlags>();
794 uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
795 uint8_t* addr = raw_addr;
796 accessor->Access(addr);
797 }
798
799 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
UpdateFieldByteViaAccessor(MemberOffset field_offset,Accessor<int8_t> * accessor)800 inline void Object::UpdateFieldByteViaAccessor(MemberOffset field_offset,
801 Accessor<int8_t>* accessor) {
802 VerifyTransaction<kTransactionActive, kCheckTransaction>();
803 if (kTransactionActive) {
804 static const bool kIsVolatile = true;
805 int8_t old_value = GetFieldByte<kVerifyFlags, kIsVolatile>(field_offset);
806 Runtime::Current()->GetClassLinker()->RecordWriteFieldByte(
807 this, field_offset, old_value, kIsVolatile);
808 }
809 Verify<kVerifyFlags>();
810 uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
811 int8_t* addr = reinterpret_cast<int8_t*>(raw_addr);
812 accessor->Access(addr);
813 }
814
815 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
UpdateFieldCharViaAccessor(MemberOffset field_offset,Accessor<uint16_t> * accessor)816 inline void Object::UpdateFieldCharViaAccessor(MemberOffset field_offset,
817 Accessor<uint16_t>* accessor) {
818 VerifyTransaction<kTransactionActive, kCheckTransaction>();
819 if (kTransactionActive) {
820 static const bool kIsVolatile = true;
821 uint16_t old_value = GetFieldChar<kVerifyFlags, kIsVolatile>(field_offset);
822 Runtime::Current()->GetClassLinker()->RecordWriteFieldChar(
823 this, field_offset, old_value, kIsVolatile);
824 }
825 Verify<kVerifyFlags>();
826 uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
827 uint16_t* addr = reinterpret_cast<uint16_t*>(raw_addr);
828 accessor->Access(addr);
829 }
830
831 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
UpdateFieldShortViaAccessor(MemberOffset field_offset,Accessor<int16_t> * accessor)832 inline void Object::UpdateFieldShortViaAccessor(MemberOffset field_offset,
833 Accessor<int16_t>* accessor) {
834 VerifyTransaction<kTransactionActive, kCheckTransaction>();
835 if (kTransactionActive) {
836 static const bool kIsVolatile = true;
837 int16_t old_value = GetFieldShort<kVerifyFlags, kIsVolatile>(field_offset);
838 Runtime::Current()->GetClassLinker()->RecordWriteFieldShort(
839 this, field_offset, old_value, kIsVolatile);
840 }
841 Verify<kVerifyFlags>();
842 uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
843 int16_t* addr = reinterpret_cast<int16_t*>(raw_addr);
844 accessor->Access(addr);
845 }
846
847 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
UpdateField32ViaAccessor(MemberOffset field_offset,Accessor<int32_t> * accessor)848 inline void Object::UpdateField32ViaAccessor(MemberOffset field_offset,
849 Accessor<int32_t>* accessor) {
850 VerifyTransaction<kTransactionActive, kCheckTransaction>();
851 if (kTransactionActive) {
852 static const bool kIsVolatile = true;
853 int32_t old_value = GetField32<kVerifyFlags, kIsVolatile>(field_offset);
854 Runtime::Current()->GetClassLinker()->RecordWriteField32(
855 this, field_offset, old_value, kIsVolatile);
856 }
857 Verify<kVerifyFlags>();
858 uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
859 int32_t* addr = reinterpret_cast<int32_t*>(raw_addr);
860 accessor->Access(addr);
861 }
862
863 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
UpdateField64ViaAccessor(MemberOffset field_offset,Accessor<int64_t> * accessor)864 inline void Object::UpdateField64ViaAccessor(MemberOffset field_offset,
865 Accessor<int64_t>* accessor) {
866 VerifyTransaction<kTransactionActive, kCheckTransaction>();
867 if (kTransactionActive) {
868 static const bool kIsVolatile = true;
869 int64_t old_value = GetField64<kVerifyFlags, kIsVolatile>(field_offset);
870 Runtime::Current()->GetClassLinker()->RecordWriteField64(
871 this, field_offset, old_value, kIsVolatile);
872 }
873 Verify<kVerifyFlags>();
874 uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
875 int64_t* addr = reinterpret_cast<int64_t*>(raw_addr);
876 accessor->Access(addr);
877 }
878
879 template <VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption, typename Visitor>
VisitInstanceFieldsReferences(ObjPtr<Class> klass,const Visitor & visitor)880 inline void Object::VisitInstanceFieldsReferences(ObjPtr<Class> klass, const Visitor& visitor) {
881 // Using NO_THREAD_SAFETY_ANALYSIS as heap_bitmap_lock_ and mutator_lock_ are
882 // required in shared/exclusive modes in all possible combinations.
883 auto visit_one_word = [&visitor, this](uint32_t field_offset, uint32_t ref_offsets)
884 NO_THREAD_SAFETY_ANALYSIS {
885 while (ref_offsets != 0) {
886 if ((ref_offsets & 1) != 0) {
887 visitor(this, MemberOffset(field_offset), /*is_static=*/false);
888 }
889 ref_offsets >>= 1;
890 field_offset += sizeof(HeapReference<Object>);
891 }
892 };
893
894 uint32_t ref_offsets = klass->GetReferenceInstanceOffsets<kVerifyFlags>();
895 DCHECK_NE(ref_offsets, 0u) << klass->PrettyDescriptor();
896 if (UNLIKELY((ref_offsets & Class::kVisitReferencesSlowpathMask) != 0)) {
897 if (kIsDebugBuild) {
898 klass->VerifyOverflowReferenceBitmap<kVerifyFlags, kReadBarrierOption>();
899 }
900 uint32_t bitmap_num_words = ref_offsets & ~Class::kVisitReferencesSlowpathMask;
901 uint32_t* overflow_bitmap = reinterpret_cast<uint32_t*>(
902 reinterpret_cast<uint8_t*>(klass.Ptr()) +
903 (klass->GetClassSize<kVerifyFlags>() - bitmap_num_words * sizeof(uint32_t)));
904 for (uint32_t i = 0; i < bitmap_num_words; i++) {
905 visit_one_word(kObjectHeaderSize + i * sizeof(HeapReference<Object>) * 32,
906 overflow_bitmap[i]);
907 }
908 } else {
909 visit_one_word(mirror::kObjectHeaderSize, ref_offsets);
910 }
911 }
912
913 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
IsClassLoader()914 inline bool Object::IsClassLoader() {
915 return GetClass<kVerifyFlags, kReadBarrierOption>()->template IsClassLoaderClass<kVerifyFlags>();
916 }
917
918 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
AsClassLoader()919 inline ObjPtr<ClassLoader> Object::AsClassLoader() {
920 DCHECK((IsClassLoader<kVerifyFlags, kReadBarrierOption>()));
921 return ObjPtr<ClassLoader>::DownCast(this);
922 }
923
924 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
IsDexCache()925 inline bool Object::IsDexCache() {
926 return GetClass<kVerifyFlags, kReadBarrierOption>()->template IsDexCacheClass<kVerifyFlags>();
927 }
928
929 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
AsDexCache()930 inline ObjPtr<mirror::DexCache> Object::AsDexCache() {
931 DCHECK((IsDexCache<kVerifyFlags, kReadBarrierOption>()));
932 return ObjPtr<DexCache>::DownCast(this);
933 }
934
935 template<bool kTransactionActive, bool kCheckTransaction>
VerifyTransaction()936 inline void Object::VerifyTransaction() {
937 if (kCheckTransaction) {
938 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
939 }
940 }
941
942 } // namespace mirror
943 } // namespace art
944
945 #endif // ART_RUNTIME_MIRROR_OBJECT_INL_H_
946