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-inl.h"
27 #include "class_flags.h"
28 #include "class_linker.h"
29 #include "class_loader-inl.h"
30 #include "dex_cache-inl.h"
31 #include "lock_word-inl.h"
32 #include "monitor.h"
33 #include "object_array-inl.h"
34 #include "object_reference-inl.h"
35 #include "object-readbarrier-inl.h"
36 #include "obj_ptr-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 return klass->IsAssignableFrom(GetClass<kVerifyFlags>());
165 }
166
167 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
IsClass()168 inline bool Object::IsClass() {
169 Class* java_lang_Class = GetClass<kVerifyFlags, kReadBarrierOption>()->
170 template GetClass<kVerifyFlags, kReadBarrierOption>();
171 return GetClass<static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis),
172 kReadBarrierOption>() == java_lang_Class;
173 }
174
175 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
AsClass()176 inline Class* Object::AsClass() {
177 DCHECK((IsClass<kVerifyFlags, kReadBarrierOption>()));
178 return down_cast<Class*>(this);
179 }
180
181 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
IsObjectArray()182 inline bool Object::IsObjectArray() {
183 constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
184 return IsArrayInstance<kVerifyFlags, kReadBarrierOption>() &&
185 !GetClass<kNewFlags, kReadBarrierOption>()->
186 template GetComponentType<kNewFlags, kReadBarrierOption>()->IsPrimitive();
187 }
188
189 template<class T, VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
AsObjectArray()190 inline ObjectArray<T>* Object::AsObjectArray() {
191 DCHECK((IsObjectArray<kVerifyFlags, kReadBarrierOption>()));
192 return down_cast<ObjectArray<T>*>(this);
193 }
194
195 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
IsArrayInstance()196 inline bool Object::IsArrayInstance() {
197 return GetClass<kVerifyFlags, kReadBarrierOption>()->
198 template IsArrayClass<kVerifyFlags, kReadBarrierOption>();
199 }
200
201 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
IsReferenceInstance()202 inline bool Object::IsReferenceInstance() {
203 return GetClass<kVerifyFlags, kReadBarrierOption>()->IsTypeOfReferenceClass();
204 }
205
206 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
AsReference()207 inline Reference* Object::AsReference() {
208 DCHECK((IsReferenceInstance<kVerifyFlags, kReadBarrierOption>()));
209 return down_cast<Reference*>(this);
210 }
211
212 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
AsArray()213 inline Array* Object::AsArray() {
214 DCHECK((IsArrayInstance<kVerifyFlags, kReadBarrierOption>()));
215 return down_cast<Array*>(this);
216 }
217
218 template<VerifyObjectFlags kVerifyFlags>
AsBooleanArray()219 inline BooleanArray* Object::AsBooleanArray() {
220 constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
221 DCHECK(GetClass<kVerifyFlags>()->IsArrayClass());
222 DCHECK(GetClass<kNewFlags>()->GetComponentType()->IsPrimitiveBoolean());
223 return down_cast<BooleanArray*>(this);
224 }
225
226 template<VerifyObjectFlags kVerifyFlags>
AsByteArray()227 inline ByteArray* Object::AsByteArray() {
228 constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
229 DCHECK(GetClass<kVerifyFlags>()->IsArrayClass());
230 DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveByte());
231 return down_cast<ByteArray*>(this);
232 }
233
234 template<VerifyObjectFlags kVerifyFlags>
AsByteSizedArray()235 inline ByteArray* Object::AsByteSizedArray() {
236 constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
237 DCHECK(GetClass<kVerifyFlags>()->IsArrayClass());
238 DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveByte() ||
239 GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveBoolean());
240 return down_cast<ByteArray*>(this);
241 }
242
243 template<VerifyObjectFlags kVerifyFlags>
AsCharArray()244 inline CharArray* Object::AsCharArray() {
245 constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
246 DCHECK(GetClass<kVerifyFlags>()->IsArrayClass());
247 DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveChar());
248 return down_cast<CharArray*>(this);
249 }
250
251 template<VerifyObjectFlags kVerifyFlags>
AsShortArray()252 inline ShortArray* Object::AsShortArray() {
253 constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
254 DCHECK(GetClass<kVerifyFlags>()->IsArrayClass());
255 DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveShort());
256 return down_cast<ShortArray*>(this);
257 }
258
259 template<VerifyObjectFlags kVerifyFlags>
AsShortSizedArray()260 inline ShortArray* Object::AsShortSizedArray() {
261 constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
262 DCHECK(GetClass<kVerifyFlags>()->IsArrayClass());
263 DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveShort() ||
264 GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveChar());
265 return down_cast<ShortArray*>(this);
266 }
267
268 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
IsIntArray()269 inline bool Object::IsIntArray() {
270 constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
271 ObjPtr<Class> klass = GetClass<kVerifyFlags, kReadBarrierOption>();
272 ObjPtr<Class> component_type = klass->GetComponentType<kVerifyFlags, kReadBarrierOption>();
273 return component_type != nullptr && component_type->template IsPrimitiveInt<kNewFlags>();
274 }
275
276 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
AsIntArray()277 inline IntArray* Object::AsIntArray() {
278 DCHECK((IsIntArray<kVerifyFlags, kReadBarrierOption>()));
279 return down_cast<IntArray*>(this);
280 }
281
282 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
IsLongArray()283 inline bool Object::IsLongArray() {
284 constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
285 ObjPtr<Class> klass = GetClass<kVerifyFlags, kReadBarrierOption>();
286 ObjPtr<Class> component_type = klass->GetComponentType<kVerifyFlags, kReadBarrierOption>();
287 return component_type != nullptr && component_type->template IsPrimitiveLong<kNewFlags>();
288 }
289
290 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
AsLongArray()291 inline LongArray* Object::AsLongArray() {
292 DCHECK((IsLongArray<kVerifyFlags, kReadBarrierOption>()));
293 return down_cast<LongArray*>(this);
294 }
295
296 template<VerifyObjectFlags kVerifyFlags>
IsFloatArray()297 inline bool Object::IsFloatArray() {
298 constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
299 auto* component_type = GetClass<kVerifyFlags>()->GetComponentType();
300 return component_type != nullptr && component_type->template IsPrimitiveFloat<kNewFlags>();
301 }
302
303 template<VerifyObjectFlags kVerifyFlags>
AsFloatArray()304 inline FloatArray* Object::AsFloatArray() {
305 DCHECK(IsFloatArray<kVerifyFlags>());
306 constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
307 DCHECK(GetClass<kVerifyFlags>()->IsArrayClass());
308 DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveFloat());
309 return down_cast<FloatArray*>(this);
310 }
311
312 template<VerifyObjectFlags kVerifyFlags>
IsDoubleArray()313 inline bool Object::IsDoubleArray() {
314 constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
315 auto* component_type = GetClass<kVerifyFlags>()->GetComponentType();
316 return component_type != nullptr && component_type->template IsPrimitiveDouble<kNewFlags>();
317 }
318
319 template<VerifyObjectFlags kVerifyFlags>
AsDoubleArray()320 inline DoubleArray* Object::AsDoubleArray() {
321 DCHECK(IsDoubleArray<kVerifyFlags>());
322 constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
323 DCHECK(GetClass<kVerifyFlags>()->IsArrayClass());
324 DCHECK(GetClass<kNewFlags>()->template GetComponentType<kNewFlags>()->IsPrimitiveDouble());
325 return down_cast<DoubleArray*>(this);
326 }
327
328 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
IsString()329 inline bool Object::IsString() {
330 return GetClass<kVerifyFlags, kReadBarrierOption>()->IsStringClass();
331 }
332
333 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
AsString()334 inline String* Object::AsString() {
335 DCHECK((IsString<kVerifyFlags, kReadBarrierOption>()));
336 return down_cast<String*>(this);
337 }
338
339 template<VerifyObjectFlags kVerifyFlags>
AsThrowable()340 inline Throwable* Object::AsThrowable() {
341 DCHECK(GetClass<kVerifyFlags>()->IsThrowableClass());
342 return down_cast<Throwable*>(this);
343 }
344
345 template<VerifyObjectFlags kVerifyFlags>
IsWeakReferenceInstance()346 inline bool Object::IsWeakReferenceInstance() {
347 return GetClass<kVerifyFlags>()->IsWeakReferenceClass();
348 }
349
350 template<VerifyObjectFlags kVerifyFlags>
IsSoftReferenceInstance()351 inline bool Object::IsSoftReferenceInstance() {
352 return GetClass<kVerifyFlags>()->IsSoftReferenceClass();
353 }
354
355 template<VerifyObjectFlags kVerifyFlags>
IsFinalizerReferenceInstance()356 inline bool Object::IsFinalizerReferenceInstance() {
357 return GetClass<kVerifyFlags>()->IsFinalizerReferenceClass();
358 }
359
360 template<VerifyObjectFlags kVerifyFlags>
AsFinalizerReference()361 inline FinalizerReference* Object::AsFinalizerReference() {
362 DCHECK(IsFinalizerReferenceInstance<kVerifyFlags>());
363 return down_cast<FinalizerReference*>(this);
364 }
365
366 template<VerifyObjectFlags kVerifyFlags>
IsPhantomReferenceInstance()367 inline bool Object::IsPhantomReferenceInstance() {
368 return GetClass<kVerifyFlags>()->IsPhantomReferenceClass();
369 }
370
371 template<VerifyObjectFlags kVerifyFlags>
SizeOf()372 inline size_t Object::SizeOf() {
373 // Read barrier is never required for SizeOf since objects sizes are constant. Reading from-space
374 // values is OK because of that.
375 static constexpr ReadBarrierOption kReadBarrierOption = kWithoutReadBarrier;
376 size_t result;
377 constexpr auto kNewFlags = static_cast<VerifyObjectFlags>(kVerifyFlags & ~kVerifyThis);
378 if (IsArrayInstance<kVerifyFlags, kReadBarrierOption>()) {
379 result = AsArray<kNewFlags, kReadBarrierOption>()->
380 template SizeOf<kNewFlags, kReadBarrierOption>();
381 } else if (IsClass<kNewFlags, kReadBarrierOption>()) {
382 result = AsClass<kNewFlags, kReadBarrierOption>()->
383 template SizeOf<kNewFlags, kReadBarrierOption>();
384 } else if (GetClass<kNewFlags, kReadBarrierOption>()->IsStringClass()) {
385 result = AsString<kNewFlags, kReadBarrierOption>()->
386 template SizeOf<kNewFlags>();
387 } else {
388 result = GetClass<kNewFlags, kReadBarrierOption>()->
389 template GetObjectSize<kNewFlags, kReadBarrierOption>();
390 }
391 DCHECK_GE(result, sizeof(Object))
392 << " class=" << Class::PrettyClass(GetClass<kNewFlags, kReadBarrierOption>());
393 return result;
394 }
395
396 template<VerifyObjectFlags kVerifyFlags, bool kIsVolatile>
GetFieldBoolean(MemberOffset field_offset)397 inline uint8_t Object::GetFieldBoolean(MemberOffset field_offset) {
398 if (kVerifyFlags & kVerifyThis) {
399 VerifyObject(this);
400 }
401 return GetField<uint8_t, kIsVolatile>(field_offset);
402 }
403
404 template<VerifyObjectFlags kVerifyFlags, bool kIsVolatile>
GetFieldByte(MemberOffset field_offset)405 inline int8_t Object::GetFieldByte(MemberOffset field_offset) {
406 if (kVerifyFlags & kVerifyThis) {
407 VerifyObject(this);
408 }
409 return GetField<int8_t, kIsVolatile>(field_offset);
410 }
411
412 template<VerifyObjectFlags kVerifyFlags>
GetFieldBooleanVolatile(MemberOffset field_offset)413 inline uint8_t Object::GetFieldBooleanVolatile(MemberOffset field_offset) {
414 return GetFieldBoolean<kVerifyFlags, true>(field_offset);
415 }
416
417 template<VerifyObjectFlags kVerifyFlags>
GetFieldByteVolatile(MemberOffset field_offset)418 inline int8_t Object::GetFieldByteVolatile(MemberOffset field_offset) {
419 return GetFieldByte<kVerifyFlags, true>(field_offset);
420 }
421
422 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags,
423 bool kIsVolatile>
SetFieldBoolean(MemberOffset field_offset,uint8_t new_value)424 inline void Object::SetFieldBoolean(MemberOffset field_offset, uint8_t new_value)
425 REQUIRES_SHARED(Locks::mutator_lock_) {
426 if (kCheckTransaction) {
427 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
428 }
429 if (kTransactionActive) {
430 Runtime::Current()->RecordWriteFieldBoolean(this, field_offset,
431 GetFieldBoolean<kVerifyFlags, kIsVolatile>(field_offset),
432 kIsVolatile);
433 }
434 if (kVerifyFlags & kVerifyThis) {
435 VerifyObject(this);
436 }
437 SetField<uint8_t, kIsVolatile>(field_offset, new_value);
438 }
439
440 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags,
441 bool kIsVolatile>
SetFieldByte(MemberOffset field_offset,int8_t new_value)442 inline void Object::SetFieldByte(MemberOffset field_offset, int8_t new_value)
443 REQUIRES_SHARED(Locks::mutator_lock_) {
444 if (kCheckTransaction) {
445 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
446 }
447 if (kTransactionActive) {
448 Runtime::Current()->RecordWriteFieldByte(this, field_offset,
449 GetFieldByte<kVerifyFlags, kIsVolatile>(field_offset),
450 kIsVolatile);
451 }
452 if (kVerifyFlags & kVerifyThis) {
453 VerifyObject(this);
454 }
455 SetField<int8_t, kIsVolatile>(field_offset, new_value);
456 }
457
458 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
SetFieldBooleanVolatile(MemberOffset field_offset,uint8_t new_value)459 inline void Object::SetFieldBooleanVolatile(MemberOffset field_offset, uint8_t new_value) {
460 return SetFieldBoolean<kTransactionActive, kCheckTransaction, kVerifyFlags, true>(
461 field_offset, new_value);
462 }
463
464 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
SetFieldByteVolatile(MemberOffset field_offset,int8_t new_value)465 inline void Object::SetFieldByteVolatile(MemberOffset field_offset, int8_t new_value) {
466 return SetFieldByte<kTransactionActive, kCheckTransaction, kVerifyFlags, true>(
467 field_offset, new_value);
468 }
469
470 template<VerifyObjectFlags kVerifyFlags, bool kIsVolatile>
GetFieldChar(MemberOffset field_offset)471 inline uint16_t Object::GetFieldChar(MemberOffset field_offset) {
472 if (kVerifyFlags & kVerifyThis) {
473 VerifyObject(this);
474 }
475 return GetField<uint16_t, kIsVolatile>(field_offset);
476 }
477
478 template<VerifyObjectFlags kVerifyFlags, bool kIsVolatile>
GetFieldShort(MemberOffset field_offset)479 inline int16_t Object::GetFieldShort(MemberOffset field_offset) {
480 if (kVerifyFlags & kVerifyThis) {
481 VerifyObject(this);
482 }
483 return GetField<int16_t, kIsVolatile>(field_offset);
484 }
485
486 template<VerifyObjectFlags kVerifyFlags>
GetFieldCharVolatile(MemberOffset field_offset)487 inline uint16_t Object::GetFieldCharVolatile(MemberOffset field_offset) {
488 return GetFieldChar<kVerifyFlags, true>(field_offset);
489 }
490
491 template<VerifyObjectFlags kVerifyFlags>
GetFieldShortVolatile(MemberOffset field_offset)492 inline int16_t Object::GetFieldShortVolatile(MemberOffset field_offset) {
493 return GetFieldShort<kVerifyFlags, true>(field_offset);
494 }
495
496 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags,
497 bool kIsVolatile>
SetFieldChar(MemberOffset field_offset,uint16_t new_value)498 inline void Object::SetFieldChar(MemberOffset field_offset, uint16_t new_value) {
499 if (kCheckTransaction) {
500 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
501 }
502 if (kTransactionActive) {
503 Runtime::Current()->RecordWriteFieldChar(this, field_offset,
504 GetFieldChar<kVerifyFlags, kIsVolatile>(field_offset),
505 kIsVolatile);
506 }
507 if (kVerifyFlags & kVerifyThis) {
508 VerifyObject(this);
509 }
510 SetField<uint16_t, kIsVolatile>(field_offset, new_value);
511 }
512
513 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags,
514 bool kIsVolatile>
SetFieldShort(MemberOffset field_offset,int16_t new_value)515 inline void Object::SetFieldShort(MemberOffset field_offset, int16_t new_value) {
516 if (kCheckTransaction) {
517 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
518 }
519 if (kTransactionActive) {
520 Runtime::Current()->RecordWriteFieldChar(this, field_offset,
521 GetFieldShort<kVerifyFlags, kIsVolatile>(field_offset),
522 kIsVolatile);
523 }
524 if (kVerifyFlags & kVerifyThis) {
525 VerifyObject(this);
526 }
527 SetField<int16_t, kIsVolatile>(field_offset, new_value);
528 }
529
530 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
SetFieldCharVolatile(MemberOffset field_offset,uint16_t new_value)531 inline void Object::SetFieldCharVolatile(MemberOffset field_offset, uint16_t new_value) {
532 return SetFieldChar<kTransactionActive, kCheckTransaction, kVerifyFlags, true>(
533 field_offset, new_value);
534 }
535
536 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
SetFieldShortVolatile(MemberOffset field_offset,int16_t new_value)537 inline void Object::SetFieldShortVolatile(MemberOffset field_offset, int16_t new_value) {
538 return SetFieldShort<kTransactionActive, kCheckTransaction, kVerifyFlags, true>(
539 field_offset, new_value);
540 }
541
542 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags,
543 bool kIsVolatile>
SetField32(MemberOffset field_offset,int32_t new_value)544 inline void Object::SetField32(MemberOffset field_offset, int32_t new_value) {
545 if (kCheckTransaction) {
546 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
547 }
548 if (kTransactionActive) {
549 Runtime::Current()->RecordWriteField32(this, field_offset,
550 GetField32<kVerifyFlags, kIsVolatile>(field_offset),
551 kIsVolatile);
552 }
553 if (kVerifyFlags & kVerifyThis) {
554 VerifyObject(this);
555 }
556 SetField<int32_t, kIsVolatile>(field_offset, new_value);
557 }
558
559 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
SetField32Volatile(MemberOffset field_offset,int32_t new_value)560 inline void Object::SetField32Volatile(MemberOffset field_offset, int32_t new_value) {
561 SetField32<kTransactionActive, kCheckTransaction, kVerifyFlags, true>(field_offset, new_value);
562 }
563
564 // TODO: Pass memory_order_ and strong/weak as arguments to avoid code duplication?
565
566 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
CasFieldWeakSequentiallyConsistent32(MemberOffset field_offset,int32_t old_value,int32_t new_value)567 inline bool Object::CasFieldWeakSequentiallyConsistent32(MemberOffset field_offset,
568 int32_t old_value, int32_t new_value) {
569 if (kCheckTransaction) {
570 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
571 }
572 if (kTransactionActive) {
573 Runtime::Current()->RecordWriteField32(this, field_offset, old_value, true);
574 }
575 if (kVerifyFlags & kVerifyThis) {
576 VerifyObject(this);
577 }
578 uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
579 AtomicInteger* atomic_addr = reinterpret_cast<AtomicInteger*>(raw_addr);
580
581 return atomic_addr->CompareExchangeWeakSequentiallyConsistent(old_value, new_value);
582 }
583
584 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
CasFieldWeakAcquire32(MemberOffset field_offset,int32_t old_value,int32_t new_value)585 inline bool Object::CasFieldWeakAcquire32(MemberOffset field_offset,
586 int32_t old_value, int32_t new_value) {
587 if (kCheckTransaction) {
588 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
589 }
590 if (kTransactionActive) {
591 Runtime::Current()->RecordWriteField32(this, field_offset, old_value, true);
592 }
593 if (kVerifyFlags & kVerifyThis) {
594 VerifyObject(this);
595 }
596 uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
597 AtomicInteger* atomic_addr = reinterpret_cast<AtomicInteger*>(raw_addr);
598
599 return atomic_addr->CompareExchangeWeakAcquire(old_value, new_value);
600 }
601
602 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
CasFieldWeakRelease32(MemberOffset field_offset,int32_t old_value,int32_t new_value)603 inline bool Object::CasFieldWeakRelease32(MemberOffset field_offset,
604 int32_t old_value, int32_t new_value) {
605 if (kCheckTransaction) {
606 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
607 }
608 if (kTransactionActive) {
609 Runtime::Current()->RecordWriteField32(this, field_offset, old_value, true);
610 }
611 if (kVerifyFlags & kVerifyThis) {
612 VerifyObject(this);
613 }
614 uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
615 AtomicInteger* atomic_addr = reinterpret_cast<AtomicInteger*>(raw_addr);
616
617 return atomic_addr->CompareExchangeWeakRelease(old_value, new_value);
618 }
619
620 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
CasFieldStrongSequentiallyConsistent32(MemberOffset field_offset,int32_t old_value,int32_t new_value)621 inline bool Object::CasFieldStrongSequentiallyConsistent32(MemberOffset field_offset,
622 int32_t old_value, int32_t new_value) {
623 if (kCheckTransaction) {
624 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
625 }
626 if (kTransactionActive) {
627 Runtime::Current()->RecordWriteField32(this, field_offset, old_value, true);
628 }
629 if (kVerifyFlags & kVerifyThis) {
630 VerifyObject(this);
631 }
632 uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
633 AtomicInteger* atomic_addr = reinterpret_cast<AtomicInteger*>(raw_addr);
634
635 return atomic_addr->CompareExchangeStrongSequentiallyConsistent(old_value, new_value);
636 }
637
638 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags,
639 bool kIsVolatile>
SetField64(MemberOffset field_offset,int64_t new_value)640 inline void Object::SetField64(MemberOffset field_offset, int64_t new_value) {
641 if (kCheckTransaction) {
642 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
643 }
644 if (kTransactionActive) {
645 Runtime::Current()->RecordWriteField64(this, field_offset,
646 GetField64<kVerifyFlags, kIsVolatile>(field_offset),
647 kIsVolatile);
648 }
649 if (kVerifyFlags & kVerifyThis) {
650 VerifyObject(this);
651 }
652 SetField<int64_t, kIsVolatile>(field_offset, new_value);
653 }
654
655 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
SetField64Volatile(MemberOffset field_offset,int64_t new_value)656 inline void Object::SetField64Volatile(MemberOffset field_offset, int64_t new_value) {
657 return SetField64<kTransactionActive, kCheckTransaction, kVerifyFlags, true>(field_offset,
658 new_value);
659 }
660
661 template<typename kSize>
GetFieldAcquire(MemberOffset field_offset)662 inline kSize Object::GetFieldAcquire(MemberOffset field_offset) {
663 const uint8_t* raw_addr = reinterpret_cast<const uint8_t*>(this) + field_offset.Int32Value();
664 const kSize* addr = reinterpret_cast<const kSize*>(raw_addr);
665 return reinterpret_cast<const Atomic<kSize>*>(addr)->LoadAcquire();
666 }
667
668 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
CasFieldWeakSequentiallyConsistent64(MemberOffset field_offset,int64_t old_value,int64_t new_value)669 inline bool Object::CasFieldWeakSequentiallyConsistent64(MemberOffset field_offset,
670 int64_t old_value, int64_t new_value) {
671 if (kCheckTransaction) {
672 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
673 }
674 if (kTransactionActive) {
675 Runtime::Current()->RecordWriteField64(this, field_offset, old_value, true);
676 }
677 if (kVerifyFlags & kVerifyThis) {
678 VerifyObject(this);
679 }
680 uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
681 Atomic<int64_t>* atomic_addr = reinterpret_cast<Atomic<int64_t>*>(raw_addr);
682 return atomic_addr->CompareExchangeWeakSequentiallyConsistent(old_value, new_value);
683 }
684
685 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
CasFieldStrongSequentiallyConsistent64(MemberOffset field_offset,int64_t old_value,int64_t new_value)686 inline bool Object::CasFieldStrongSequentiallyConsistent64(MemberOffset field_offset,
687 int64_t old_value, int64_t new_value) {
688 if (kCheckTransaction) {
689 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
690 }
691 if (kTransactionActive) {
692 Runtime::Current()->RecordWriteField64(this, field_offset, old_value, true);
693 }
694 if (kVerifyFlags & kVerifyThis) {
695 VerifyObject(this);
696 }
697 uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
698 Atomic<int64_t>* atomic_addr = reinterpret_cast<Atomic<int64_t>*>(raw_addr);
699 return atomic_addr->CompareExchangeStrongSequentiallyConsistent(old_value, new_value);
700 }
701
702 template<class T, VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption,
703 bool kIsVolatile>
GetFieldObject(MemberOffset field_offset)704 inline T* Object::GetFieldObject(MemberOffset field_offset) {
705 if (kVerifyFlags & kVerifyThis) {
706 VerifyObject(this);
707 }
708 uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
709 HeapReference<T>* objref_addr = reinterpret_cast<HeapReference<T>*>(raw_addr);
710 T* result = ReadBarrier::Barrier<T, kReadBarrierOption>(this, field_offset, objref_addr);
711 if (kIsVolatile) {
712 // TODO: Refactor to use a SequentiallyConsistent load instead.
713 QuasiAtomic::ThreadFenceAcquire(); // Ensure visibility of operations preceding store.
714 }
715 if (kVerifyFlags & kVerifyReads) {
716 VerifyObject(result);
717 }
718 return result;
719 }
720
721 template<class T, VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
GetFieldObjectVolatile(MemberOffset field_offset)722 inline T* Object::GetFieldObjectVolatile(MemberOffset field_offset) {
723 return GetFieldObject<T, kVerifyFlags, kReadBarrierOption, true>(field_offset);
724 }
725
726 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags,
727 bool kIsVolatile>
SetFieldObjectWithoutWriteBarrier(MemberOffset field_offset,ObjPtr<Object> new_value)728 inline void Object::SetFieldObjectWithoutWriteBarrier(MemberOffset field_offset,
729 ObjPtr<Object> new_value) {
730 if (kCheckTransaction) {
731 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
732 }
733 if (kTransactionActive) {
734 ObjPtr<Object> obj;
735 if (kIsVolatile) {
736 obj = GetFieldObjectVolatile<Object>(field_offset);
737 } else {
738 obj = GetFieldObject<Object>(field_offset);
739 }
740 Runtime::Current()->RecordWriteFieldReference(this, field_offset, obj.Ptr(), true);
741 }
742 if (kVerifyFlags & kVerifyThis) {
743 VerifyObject(this);
744 }
745 if (kVerifyFlags & kVerifyWrites) {
746 VerifyObject(new_value);
747 }
748 uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
749 HeapReference<Object>* objref_addr = reinterpret_cast<HeapReference<Object>*>(raw_addr);
750 if (kIsVolatile) {
751 // TODO: Refactor to use a SequentiallyConsistent store instead.
752 QuasiAtomic::ThreadFenceRelease(); // Ensure that prior accesses are visible before store.
753 objref_addr->Assign(new_value.Ptr());
754 QuasiAtomic::ThreadFenceSequentiallyConsistent();
755 // Ensure this store occurs before any volatile loads.
756 } else {
757 objref_addr->Assign(new_value.Ptr());
758 }
759 }
760
761 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags,
762 bool kIsVolatile>
SetFieldObject(MemberOffset field_offset,ObjPtr<Object> new_value)763 inline void Object::SetFieldObject(MemberOffset field_offset, ObjPtr<Object> new_value) {
764 SetFieldObjectWithoutWriteBarrier<kTransactionActive, kCheckTransaction, kVerifyFlags,
765 kIsVolatile>(field_offset, new_value);
766 if (new_value != nullptr) {
767 Runtime::Current()->GetHeap()->WriteBarrierField(this, field_offset, new_value);
768 // TODO: Check field assignment could theoretically cause thread suspension, TODO: fix this.
769 CheckFieldAssignment(field_offset, new_value);
770 }
771 }
772
773 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
SetFieldObjectVolatile(MemberOffset field_offset,ObjPtr<Object> new_value)774 inline void Object::SetFieldObjectVolatile(MemberOffset field_offset, ObjPtr<Object> new_value) {
775 SetFieldObject<kTransactionActive, kCheckTransaction, kVerifyFlags, true>(field_offset,
776 new_value);
777 }
778
779 template <VerifyObjectFlags kVerifyFlags>
GetFieldObjectReferenceAddr(MemberOffset field_offset)780 inline HeapReference<Object>* Object::GetFieldObjectReferenceAddr(MemberOffset field_offset) {
781 if (kVerifyFlags & kVerifyThis) {
782 VerifyObject(this);
783 }
784 return reinterpret_cast<HeapReference<Object>*>(reinterpret_cast<uint8_t*>(this) +
785 field_offset.Int32Value());
786 }
787
788 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
CasFieldWeakSequentiallyConsistentObject(MemberOffset field_offset,ObjPtr<Object> old_value,ObjPtr<Object> new_value)789 inline bool Object::CasFieldWeakSequentiallyConsistentObject(MemberOffset field_offset,
790 ObjPtr<Object> old_value,
791 ObjPtr<Object> new_value) {
792 bool success = CasFieldWeakSequentiallyConsistentObjectWithoutWriteBarrier<
793 kTransactionActive, kCheckTransaction, kVerifyFlags>(field_offset, old_value, new_value);
794 if (success) {
795 Runtime::Current()->GetHeap()->WriteBarrierField(this, field_offset, new_value);
796 }
797 return success;
798 }
799
800 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
CasFieldWeakSequentiallyConsistentObjectWithoutWriteBarrier(MemberOffset field_offset,ObjPtr<Object> old_value,ObjPtr<Object> new_value)801 inline bool Object::CasFieldWeakSequentiallyConsistentObjectWithoutWriteBarrier(
802 MemberOffset field_offset,
803 ObjPtr<Object> old_value,
804 ObjPtr<Object> new_value) {
805 if (kCheckTransaction) {
806 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
807 }
808 if (kVerifyFlags & kVerifyThis) {
809 VerifyObject(this);
810 }
811 if (kVerifyFlags & kVerifyWrites) {
812 VerifyObject(new_value);
813 }
814 if (kVerifyFlags & kVerifyReads) {
815 VerifyObject(old_value);
816 }
817 if (kTransactionActive) {
818 Runtime::Current()->RecordWriteFieldReference(this, field_offset, old_value, true);
819 }
820 HeapReference<Object> old_ref(HeapReference<Object>::FromObjPtr(old_value));
821 HeapReference<Object> new_ref(HeapReference<Object>::FromObjPtr(new_value));
822 uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
823 Atomic<uint32_t>* atomic_addr = reinterpret_cast<Atomic<uint32_t>*>(raw_addr);
824
825 bool success = atomic_addr->CompareExchangeWeakSequentiallyConsistent(old_ref.reference_,
826 new_ref.reference_);
827 return success;
828 }
829
830 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
CasFieldStrongSequentiallyConsistentObject(MemberOffset field_offset,ObjPtr<Object> old_value,ObjPtr<Object> new_value)831 inline bool Object::CasFieldStrongSequentiallyConsistentObject(MemberOffset field_offset,
832 ObjPtr<Object> old_value,
833 ObjPtr<Object> new_value) {
834 bool success = CasFieldStrongSequentiallyConsistentObjectWithoutWriteBarrier<
835 kTransactionActive, kCheckTransaction, kVerifyFlags>(field_offset, old_value, new_value);
836 if (success) {
837 Runtime::Current()->GetHeap()->WriteBarrierField(this, field_offset, new_value);
838 }
839 return success;
840 }
841
842 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
CasFieldStrongSequentiallyConsistentObjectWithoutWriteBarrier(MemberOffset field_offset,ObjPtr<Object> old_value,ObjPtr<Object> new_value)843 inline bool Object::CasFieldStrongSequentiallyConsistentObjectWithoutWriteBarrier(
844 MemberOffset field_offset,
845 ObjPtr<Object> old_value,
846 ObjPtr<Object> new_value) {
847 if (kCheckTransaction) {
848 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
849 }
850 if (kVerifyFlags & kVerifyThis) {
851 VerifyObject(this);
852 }
853 if (kVerifyFlags & kVerifyWrites) {
854 VerifyObject(new_value);
855 }
856 if (kVerifyFlags & kVerifyReads) {
857 VerifyObject(old_value);
858 }
859 if (kTransactionActive) {
860 Runtime::Current()->RecordWriteFieldReference(this, field_offset, old_value, true);
861 }
862 HeapReference<Object> old_ref(HeapReference<Object>::FromObjPtr(old_value));
863 HeapReference<Object> new_ref(HeapReference<Object>::FromObjPtr(new_value));
864 uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
865 Atomic<uint32_t>* atomic_addr = reinterpret_cast<Atomic<uint32_t>*>(raw_addr);
866
867 bool success = atomic_addr->CompareExchangeStrongSequentiallyConsistent(old_ref.reference_,
868 new_ref.reference_);
869 return success;
870 }
871
872 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
CasFieldWeakRelaxedObjectWithoutWriteBarrier(MemberOffset field_offset,ObjPtr<Object> old_value,ObjPtr<Object> new_value)873 inline bool Object::CasFieldWeakRelaxedObjectWithoutWriteBarrier(
874 MemberOffset field_offset,
875 ObjPtr<Object> old_value,
876 ObjPtr<Object> new_value) {
877 if (kCheckTransaction) {
878 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
879 }
880 if (kVerifyFlags & kVerifyThis) {
881 VerifyObject(this);
882 }
883 if (kVerifyFlags & kVerifyWrites) {
884 VerifyObject(new_value);
885 }
886 if (kVerifyFlags & kVerifyReads) {
887 VerifyObject(old_value);
888 }
889 if (kTransactionActive) {
890 Runtime::Current()->RecordWriteFieldReference(this, field_offset, old_value, true);
891 }
892 HeapReference<Object> old_ref(HeapReference<Object>::FromObjPtr(old_value));
893 HeapReference<Object> new_ref(HeapReference<Object>::FromObjPtr(new_value));
894 uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
895 Atomic<uint32_t>* atomic_addr = reinterpret_cast<Atomic<uint32_t>*>(raw_addr);
896
897 bool success = atomic_addr->CompareExchangeWeakRelaxed(old_ref.reference_,
898 new_ref.reference_);
899 return success;
900 }
901
902 template<bool kTransactionActive, bool kCheckTransaction, VerifyObjectFlags kVerifyFlags>
CasFieldWeakReleaseObjectWithoutWriteBarrier(MemberOffset field_offset,ObjPtr<Object> old_value,ObjPtr<Object> new_value)903 inline bool Object::CasFieldWeakReleaseObjectWithoutWriteBarrier(
904 MemberOffset field_offset,
905 ObjPtr<Object> old_value,
906 ObjPtr<Object> new_value) {
907 if (kCheckTransaction) {
908 DCHECK_EQ(kTransactionActive, Runtime::Current()->IsActiveTransaction());
909 }
910 if (kVerifyFlags & kVerifyThis) {
911 VerifyObject(this);
912 }
913 if (kVerifyFlags & kVerifyWrites) {
914 VerifyObject(new_value);
915 }
916 if (kVerifyFlags & kVerifyReads) {
917 VerifyObject(old_value);
918 }
919 if (kTransactionActive) {
920 Runtime::Current()->RecordWriteFieldReference(this, field_offset, old_value, true);
921 }
922 HeapReference<Object> old_ref(HeapReference<Object>::FromObjPtr(old_value));
923 HeapReference<Object> new_ref(HeapReference<Object>::FromObjPtr(new_value));
924 uint8_t* raw_addr = reinterpret_cast<uint8_t*>(this) + field_offset.Int32Value();
925 Atomic<uint32_t>* atomic_addr = reinterpret_cast<Atomic<uint32_t>*>(raw_addr);
926
927 bool success = atomic_addr->CompareExchangeWeakRelease(old_ref.reference_,
928 new_ref.reference_);
929 return success;
930 }
931
932 template<bool kIsStatic,
933 VerifyObjectFlags kVerifyFlags,
934 ReadBarrierOption kReadBarrierOption,
935 typename Visitor>
VisitFieldsReferences(uint32_t ref_offsets,const Visitor & visitor)936 inline void Object::VisitFieldsReferences(uint32_t ref_offsets, const Visitor& visitor) {
937 if (!kIsStatic && (ref_offsets != mirror::Class::kClassWalkSuper)) {
938 // Instance fields and not the slow-path.
939 uint32_t field_offset = mirror::kObjectHeaderSize;
940 while (ref_offsets != 0) {
941 if ((ref_offsets & 1) != 0) {
942 visitor(this, MemberOffset(field_offset), kIsStatic);
943 }
944 ref_offsets >>= 1;
945 field_offset += sizeof(mirror::HeapReference<mirror::Object>);
946 }
947 } else {
948 // There is no reference offset bitmap. In the non-static case, walk up the class
949 // inheritance hierarchy and find reference offsets the hard way. In the static case, just
950 // consider this class.
951 for (ObjPtr<Class> klass = kIsStatic
952 ? AsClass<kVerifyFlags, kReadBarrierOption>()
953 : GetClass<kVerifyFlags, kReadBarrierOption>();
954 klass != nullptr;
955 klass = kIsStatic ? nullptr : klass->GetSuperClass<kVerifyFlags, kReadBarrierOption>()) {
956 const size_t num_reference_fields =
957 kIsStatic ? klass->NumReferenceStaticFields() : klass->NumReferenceInstanceFields();
958 if (num_reference_fields == 0u) {
959 continue;
960 }
961 // Presumably GC can happen when we are cross compiling, it should not cause performance
962 // problems to do pointer size logic.
963 MemberOffset field_offset = kIsStatic
964 ? klass->GetFirstReferenceStaticFieldOffset<kVerifyFlags, kReadBarrierOption>(
965 Runtime::Current()->GetClassLinker()->GetImagePointerSize())
966 : klass->GetFirstReferenceInstanceFieldOffset<kVerifyFlags, kReadBarrierOption>();
967 for (size_t i = 0u; i < num_reference_fields; ++i) {
968 // TODO: Do a simpler check?
969 if (field_offset.Uint32Value() != ClassOffset().Uint32Value()) {
970 visitor(this, field_offset, kIsStatic);
971 }
972 field_offset = MemberOffset(field_offset.Uint32Value() +
973 sizeof(mirror::HeapReference<mirror::Object>));
974 }
975 }
976 }
977 }
978
979 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption, typename Visitor>
VisitInstanceFieldsReferences(ObjPtr<Class> klass,const Visitor & visitor)980 inline void Object::VisitInstanceFieldsReferences(ObjPtr<Class> klass, const Visitor& visitor) {
981 VisitFieldsReferences<false, kVerifyFlags, kReadBarrierOption>(
982 klass->GetReferenceInstanceOffsets<kVerifyFlags>(), visitor);
983 }
984
985 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption, typename Visitor>
VisitStaticFieldsReferences(ObjPtr<Class> klass,const Visitor & visitor)986 inline void Object::VisitStaticFieldsReferences(ObjPtr<Class> klass, const Visitor& visitor) {
987 DCHECK(!klass->IsTemp());
988 klass->VisitFieldsReferences<true, kVerifyFlags, kReadBarrierOption>(0, visitor);
989 }
990
991 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
IsClassLoader()992 inline bool Object::IsClassLoader() {
993 return GetClass<kVerifyFlags, kReadBarrierOption>()->IsClassLoaderClass();
994 }
995
996 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
AsClassLoader()997 inline mirror::ClassLoader* Object::AsClassLoader() {
998 DCHECK((IsClassLoader<kVerifyFlags, kReadBarrierOption>()));
999 return down_cast<mirror::ClassLoader*>(this);
1000 }
1001
1002 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
IsDexCache()1003 inline bool Object::IsDexCache() {
1004 return GetClass<kVerifyFlags, kReadBarrierOption>()->IsDexCacheClass();
1005 }
1006
1007 template<VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption>
AsDexCache()1008 inline mirror::DexCache* Object::AsDexCache() {
1009 DCHECK((IsDexCache<kVerifyFlags, kReadBarrierOption>()));
1010 return down_cast<mirror::DexCache*>(this);
1011 }
1012
1013 } // namespace mirror
1014 } // namespace art
1015
1016 #endif // ART_RUNTIME_MIRROR_OBJECT_INL_H_
1017