summaryrefslogtreecommitdiffstats
path: root/runtime/mirror/object-inl.h
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/mirror/object-inl.h')
-rw-r--r--runtime/mirror/object-inl.h165
1 files changed, 106 insertions, 59 deletions
diff --git a/runtime/mirror/object-inl.h b/runtime/mirror/object-inl.h
index 9161bc578c..afa411204b 100644
--- a/runtime/mirror/object-inl.h
+++ b/runtime/mirror/object-inl.h
@@ -32,19 +32,18 @@
namespace art {
namespace mirror {
-inline Class* Object::GetClass() const {
- return GetFieldObject<Class*>(OFFSET_OF_OBJECT_MEMBER(Object, klass_), false);
+inline Class* Object::GetClass() {
+ return GetFieldObject<Class>(OFFSET_OF_OBJECT_MEMBER(Object, klass_), false);
}
inline void Object::SetClass(Class* new_klass) {
- // new_klass may be NULL prior to class linker initialization
- // We don't mark the card since the class is guaranteed to be referenced from another location.
- // Proxy classes are held live by the class loader, and other classes are roots of the class
- // linker.
- SetFieldPtr(OFFSET_OF_OBJECT_MEMBER(Object, klass_), new_klass, false, false);
+ // new_klass may be NULL prior to class linker initialization.
+ // We don't mark the card as this occurs as part of object allocation. Not all objects have
+ // backing cards, such as large objects.
+ SetFieldObjectWithoutWriteBarrier(OFFSET_OF_OBJECT_MEMBER(Object, klass_), new_klass, false, false);
}
-inline LockWord Object::GetLockWord() const {
+inline LockWord Object::GetLockWord() {
return LockWord(GetField32(OFFSET_OF_OBJECT_MEMBER(Object, monitor_), true));
}
@@ -85,19 +84,19 @@ inline void Object::Wait(Thread* self, int64_t ms, int32_t ns) {
Monitor::Wait(self, this, ms, ns, true, kTimedWaiting);
}
-inline bool Object::VerifierInstanceOf(const Class* klass) const {
+inline bool Object::VerifierInstanceOf(Class* klass) {
DCHECK(klass != NULL);
DCHECK(GetClass() != NULL);
return klass->IsInterface() || InstanceOf(klass);
}
-inline bool Object::InstanceOf(const Class* klass) const {
+inline bool Object::InstanceOf(Class* klass) {
DCHECK(klass != NULL);
DCHECK(GetClass() != NULL);
return klass->IsAssignableFrom(GetClass());
}
-inline bool Object::IsClass() const {
+inline bool Object::IsClass() {
Class* java_lang_Class = GetClass()->GetClass();
return GetClass() == java_lang_Class;
}
@@ -107,12 +106,7 @@ inline Class* Object::AsClass() {
return down_cast<Class*>(this);
}
-inline const Class* Object::AsClass() const {
- DCHECK(IsClass());
- return down_cast<const Class*>(this);
-}
-
-inline bool Object::IsObjectArray() const {
+inline bool Object::IsObjectArray() {
return IsArrayInstance() && !GetClass()->GetComponentType()->IsPrimitive();
}
@@ -122,17 +116,11 @@ inline ObjectArray<T>* Object::AsObjectArray() {
return down_cast<ObjectArray<T>*>(this);
}
-template<class T>
-inline const ObjectArray<T>* Object::AsObjectArray() const {
- DCHECK(IsObjectArray());
- return down_cast<const ObjectArray<T>*>(this);
-}
-
-inline bool Object::IsArrayInstance() const {
+inline bool Object::IsArrayInstance() {
return GetClass()->IsArrayClass();
}
-inline bool Object::IsArtField() const {
+inline bool Object::IsArtField() {
return GetClass()->IsArtFieldClass();
}
@@ -141,12 +129,7 @@ inline ArtField* Object::AsArtField() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_
return down_cast<ArtField*>(this);
}
-inline const ArtField* Object::AsArtField() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- DCHECK(IsArtField());
- return down_cast<const ArtField*>(this);
-}
-
-inline bool Object::IsArtMethod() const {
+inline bool Object::IsArtMethod() {
return GetClass()->IsArtMethodClass();
}
@@ -155,12 +138,7 @@ inline ArtMethod* Object::AsArtMethod() {
return down_cast<ArtMethod*>(this);
}
-inline const ArtMethod* Object::AsArtMethod() const {
- DCHECK(IsArtMethod());
- return down_cast<const ArtMethod*>(this);
-}
-
-inline bool Object::IsReferenceInstance() const {
+inline bool Object::IsReferenceInstance() {
return GetClass()->IsReferenceClass();
}
@@ -169,11 +147,6 @@ inline Array* Object::AsArray() {
return down_cast<Array*>(this);
}
-inline const Array* Object::AsArray() const {
- DCHECK(IsArrayInstance());
- return down_cast<const Array*>(this);
-}
-
inline BooleanArray* Object::AsBooleanArray() {
DCHECK(GetClass()->IsArrayClass());
DCHECK(GetClass()->GetComponentType()->IsPrimitiveBoolean());
@@ -186,6 +159,13 @@ inline ByteArray* Object::AsByteArray() {
return down_cast<ByteArray*>(this);
}
+inline ByteArray* Object::AsByteSizedArray() {
+ DCHECK(GetClass()->IsArrayClass());
+ DCHECK(GetClass()->GetComponentType()->IsPrimitiveByte() ||
+ GetClass()->GetComponentType()->IsPrimitiveBoolean());
+ return down_cast<ByteArray*>(this);
+}
+
inline CharArray* Object::AsCharArray() {
DCHECK(GetClass()->IsArrayClass());
DCHECK(GetClass()->GetComponentType()->IsPrimitiveChar());
@@ -198,6 +178,13 @@ inline ShortArray* Object::AsShortArray() {
return down_cast<ShortArray*>(this);
}
+inline ShortArray* Object::AsShortSizedArray() {
+ DCHECK(GetClass()->IsArrayClass());
+ DCHECK(GetClass()->GetComponentType()->IsPrimitiveShort() ||
+ GetClass()->GetComponentType()->IsPrimitiveChar());
+ return down_cast<ShortArray*>(this);
+}
+
inline IntArray* Object::AsIntArray() {
DCHECK(GetClass()->IsArrayClass());
DCHECK(GetClass()->GetComponentType()->IsPrimitiveInt() ||
@@ -222,23 +209,23 @@ inline Throwable* Object::AsThrowable() {
return down_cast<Throwable*>(this);
}
-inline bool Object::IsWeakReferenceInstance() const {
+inline bool Object::IsWeakReferenceInstance() {
return GetClass()->IsWeakReferenceClass();
}
-inline bool Object::IsSoftReferenceInstance() const {
+inline bool Object::IsSoftReferenceInstance() {
return GetClass()->IsSoftReferenceClass();
}
-inline bool Object::IsFinalizerReferenceInstance() const {
+inline bool Object::IsFinalizerReferenceInstance() {
return GetClass()->IsFinalizerReferenceClass();
}
-inline bool Object::IsPhantomReferenceInstance() const {
+inline bool Object::IsPhantomReferenceInstance() {
return GetClass()->IsPhantomReferenceClass();
}
-inline size_t Object::SizeOf() const {
+inline size_t Object::SizeOf() {
size_t result;
if (IsArrayInstance()) {
result = AsArray()->SizeOf();
@@ -253,13 +240,13 @@ inline size_t Object::SizeOf() const {
return result;
}
-inline uint32_t Object::GetField32(MemberOffset field_offset, bool is_volatile) const {
+inline uint32_t Object::GetField32(MemberOffset field_offset, bool is_volatile) {
VerifyObject(this);
const byte* raw_addr = reinterpret_cast<const byte*>(this) + field_offset.Int32Value();
const int32_t* word_addr = reinterpret_cast<const int32_t*>(raw_addr);
if (UNLIKELY(is_volatile)) {
int32_t result = *(reinterpret_cast<volatile int32_t*>(const_cast<int32_t*>(word_addr)));
- QuasiAtomic::MembarLoadLoad();
+ QuasiAtomic::MembarLoadLoad(); // Ensure volatile loads don't re-order.
return result;
} else {
return *word_addr;
@@ -276,7 +263,7 @@ inline void Object::SetField32(MemberOffset field_offset, uint32_t new_value, bo
if (UNLIKELY(is_volatile)) {
QuasiAtomic::MembarStoreStore(); // Ensure this store occurs after others in the queue.
*word_addr = new_value;
- QuasiAtomic::MembarStoreLoad(); // Ensure this store occurs before any loads.
+ QuasiAtomic::MembarStoreLoad(); // Ensure this store occurs before any volatile loads.
} else {
*word_addr = new_value;
}
@@ -289,28 +276,31 @@ inline bool Object::CasField32(MemberOffset field_offset, uint32_t old_value, ui
return __sync_bool_compare_and_swap(addr, old_value, new_value);
}
-inline uint64_t Object::GetField64(MemberOffset field_offset, bool is_volatile) const {
+inline uint64_t Object::GetField64(MemberOffset field_offset, bool is_volatile) {
VerifyObject(this);
const byte* raw_addr = reinterpret_cast<const byte*>(this) + field_offset.Int32Value();
const int64_t* addr = reinterpret_cast<const int64_t*>(raw_addr);
if (UNLIKELY(is_volatile)) {
uint64_t result = QuasiAtomic::Read64(addr);
- QuasiAtomic::MembarLoadLoad();
+ QuasiAtomic::MembarLoadLoad(); // Ensure volatile loads don't re-order.
return result;
} else {
return *addr;
}
}
-inline void Object::SetField64(MemberOffset field_offset, uint64_t new_value, bool is_volatile) {
- VerifyObject(this);
+inline void Object::SetField64(MemberOffset field_offset, uint64_t new_value, bool is_volatile,
+ bool this_is_valid) {
+ if (this_is_valid) {
+ VerifyObject(this);
+ }
byte* raw_addr = reinterpret_cast<byte*>(this) + field_offset.Int32Value();
int64_t* addr = reinterpret_cast<int64_t*>(raw_addr);
if (UNLIKELY(is_volatile)) {
QuasiAtomic::MembarStoreStore(); // Ensure this store occurs after others in the queue.
QuasiAtomic::Write64(addr, new_value);
if (!QuasiAtomic::LongAtomicsUseMutexes()) {
- QuasiAtomic::MembarStoreLoad(); // Ensure this store occurs before any loads.
+ QuasiAtomic::MembarStoreLoad(); // Ensure this store occurs before any volatile loads.
} else {
// Fence from from mutex is enough.
}
@@ -319,12 +309,69 @@ inline void Object::SetField64(MemberOffset field_offset, uint64_t new_value, bo
}
}
-inline void Object::WriteBarrierField(const Object* dst, MemberOffset field_offset,
- const Object* new_value) {
- Runtime::Current()->GetHeap()->WriteBarrierField(dst, field_offset, new_value);
+inline bool Object::CasField64(MemberOffset field_offset, uint64_t old_value, uint64_t new_value) {
+ VerifyObject(this);
+ byte* raw_addr = reinterpret_cast<byte*>(this) + field_offset.Int32Value();
+ volatile uint64_t* addr = reinterpret_cast<volatile uint64_t*>(raw_addr);
+ return __sync_bool_compare_and_swap(addr, old_value, new_value);
+}
+
+template<class T>
+inline T* Object::GetFieldObject(MemberOffset field_offset, bool is_volatile) {
+ VerifyObject(this);
+ byte* raw_addr = reinterpret_cast<byte*>(this) + field_offset.Int32Value();
+ HeapReference<T>* objref_addr = reinterpret_cast<HeapReference<T>*>(raw_addr);
+ HeapReference<T> objref = *objref_addr;
+
+ if (UNLIKELY(is_volatile)) {
+ QuasiAtomic::MembarLoadLoad(); // Ensure loads don't re-order.
+ }
+ T* result = objref.AsMirrorPtr();
+ VerifyObject(result);
+ return result;
+}
+
+inline void Object::SetFieldObjectWithoutWriteBarrier(MemberOffset field_offset, Object* new_value,
+ bool is_volatile, bool this_is_valid) {
+ if (this_is_valid) {
+ VerifyObject(this);
+ }
+ VerifyObject(new_value);
+ HeapReference<Object> objref(HeapReference<Object>::FromMirrorPtr(new_value));
+ byte* raw_addr = reinterpret_cast<byte*>(this) + field_offset.Int32Value();
+ HeapReference<Object>* objref_addr = reinterpret_cast<HeapReference<Object>*>(raw_addr);
+ if (UNLIKELY(is_volatile)) {
+ QuasiAtomic::MembarStoreStore(); // Ensure this store occurs after others in the queue.
+ objref_addr->Assign(new_value);
+ QuasiAtomic::MembarStoreLoad(); // Ensure this store occurs before any loads.
+ } else {
+ objref_addr->Assign(new_value);
+ }
+}
+
+inline void Object::SetFieldObject(MemberOffset field_offset, Object* new_value, bool is_volatile,
+ bool this_is_valid) {
+ SetFieldObjectWithoutWriteBarrier(field_offset, new_value, is_volatile, this_is_valid);
+ if (new_value != nullptr) {
+ CheckFieldAssignment(field_offset, new_value);
+ Runtime::Current()->GetHeap()->WriteBarrierField(this, field_offset, new_value);
+ }
+}
+
+inline bool Object::CasFieldObject(MemberOffset field_offset, Object* old_value, Object* new_value) {
+ VerifyObject(this);
+ byte* raw_addr = reinterpret_cast<byte*>(this) + field_offset.Int32Value();
+ volatile uint32_t* addr = reinterpret_cast<volatile uint32_t*>(raw_addr);
+ HeapReference<Object> old_ref(HeapReference<Object>::FromMirrorPtr(old_value));
+ HeapReference<Object> new_ref(HeapReference<Object>::FromMirrorPtr(new_value));
+ bool success = __sync_bool_compare_and_swap(addr, old_ref.reference_, new_ref.reference_);
+ if (success) {
+ Runtime::Current()->GetHeap()->WriteBarrierField(this, field_offset, new_value);
+ }
+ return success;
}
-inline void Object::VerifyObject(const Object* obj) {
+inline void Object::VerifyObject(Object* obj) {
if (kIsDebugBuild) {
Runtime::Current()->GetHeap()->VerifyObject(obj);
}