/* * Copyright (C) 2011 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef ART_RUNTIME_MIRROR_OBJECT_INL_H_ #define ART_RUNTIME_MIRROR_OBJECT_INL_H_ #include "object.h" #include "art_field.h" #include "art_method.h" #include "atomic.h" #include "array-inl.h" #include "class.h" #include "monitor.h" #include "runtime.h" #include "throwable.h" namespace art { namespace mirror { inline Class* Object::GetClass() const { 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); } inline uint32_t Object::GetThinLockId() { return Monitor::GetThinLockId(monitor_); } inline void Object::MonitorEnter(Thread* self) { Monitor::MonitorEnter(self, this); } inline bool Object::MonitorExit(Thread* self) { return Monitor::MonitorExit(self, this); } inline void Object::Notify(Thread* self) { Monitor::Notify(self, this); } inline void Object::NotifyAll(Thread* self) { Monitor::NotifyAll(self, this); } inline void Object::Wait(Thread* self) { Monitor::Wait(self, this, 0, 0, true, kWaiting); } 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 { DCHECK(klass != NULL); DCHECK(GetClass() != NULL); return klass->IsInterface() || InstanceOf(klass); } inline bool Object::InstanceOf(const Class* klass) const { DCHECK(klass != NULL); DCHECK(GetClass() != NULL); return klass->IsAssignableFrom(GetClass()); } inline bool Object::IsClass() const { Class* java_lang_Class = GetClass()->GetClass(); return GetClass() == java_lang_Class; } inline Class* Object::AsClass() { DCHECK(IsClass()); return down_cast<Class*>(this); } inline const Class* Object::AsClass() const { DCHECK(IsClass()); return down_cast<const Class*>(this); } inline bool Object::IsObjectArray() const { return IsArrayInstance() && !GetClass()->GetComponentType()->IsPrimitive(); } template<class T> inline ObjectArray<T>* Object::AsObjectArray() { DCHECK(IsObjectArray()); 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 { return GetClass()->IsArrayClass(); } inline bool Object::IsArtField() const { return GetClass()->IsArtFieldClass(); } inline ArtField* Object::AsArtField() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { DCHECK(IsArtField()); 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 { return GetClass()->IsArtMethodClass(); } inline ArtMethod* Object::AsArtMethod() { DCHECK(IsArtMethod()); return down_cast<ArtMethod*>(this); } inline const ArtMethod* Object::AsArtMethod() const { DCHECK(IsArtMethod()); return down_cast<const ArtMethod*>(this); } inline bool Object::IsReferenceInstance() const { return GetClass()->IsReferenceClass(); } inline Array* Object::AsArray() { DCHECK(IsArrayInstance()); 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()); return down_cast<BooleanArray*>(this); } inline ByteArray* Object::AsByteArray() { DCHECK(GetClass()->IsArrayClass()); DCHECK(GetClass()->GetComponentType()->IsPrimitiveByte()); return down_cast<ByteArray*>(this); } inline CharArray* Object::AsCharArray() { DCHECK(GetClass()->IsArrayClass()); DCHECK(GetClass()->GetComponentType()->IsPrimitiveChar()); return down_cast<CharArray*>(this); } inline ShortArray* Object::AsShortArray() { DCHECK(GetClass()->IsArrayClass()); DCHECK(GetClass()->GetComponentType()->IsPrimitiveShort()); return down_cast<ShortArray*>(this); } inline IntArray* Object::AsIntArray() { DCHECK(GetClass()->IsArrayClass()); DCHECK(GetClass()->GetComponentType()->IsPrimitiveInt() || GetClass()->GetComponentType()->IsPrimitiveFloat()); return down_cast<IntArray*>(this); } inline LongArray* Object::AsLongArray() { DCHECK(GetClass()->IsArrayClass()); DCHECK(GetClass()->GetComponentType()->IsPrimitiveLong() || GetClass()->GetComponentType()->IsPrimitiveDouble()); return down_cast<LongArray*>(this); } inline String* Object::AsString() { DCHECK(GetClass()->IsStringClass()); return down_cast<String*>(this); } inline Throwable* Object::AsThrowable() { DCHECK(GetClass()->IsThrowableClass()); return down_cast<Throwable*>(this); } inline bool Object::IsWeakReferenceInstance() const { return GetClass()->IsWeakReferenceClass(); } inline bool Object::IsSoftReferenceInstance() const { return GetClass()->IsSoftReferenceClass(); } inline bool Object::IsFinalizerReferenceInstance() const { return GetClass()->IsFinalizerReferenceClass(); } inline bool Object::IsPhantomReferenceInstance() const { return GetClass()->IsPhantomReferenceClass(); } inline size_t Object::SizeOf() const { size_t result; if (IsArrayInstance()) { result = AsArray()->SizeOf(); } else if (IsClass()) { result = AsClass()->SizeOf(); } else { result = GetClass()->GetObjectSize(); } DCHECK(!IsArtField() || result == sizeof(ArtField)); DCHECK(!IsArtMethod() || result == sizeof(ArtMethod)); return result; } inline uint64_t Object::GetField64(MemberOffset field_offset, bool is_volatile) const { 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); ANDROID_MEMBAR_FULL(); return result; } else { return *addr; } } inline void Object::SetField64(MemberOffset field_offset, uint64_t new_value, bool is_volatile) { 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)) { ANDROID_MEMBAR_STORE(); QuasiAtomic::Write64(addr, new_value); // Post-store barrier not required due to use of atomic op or mutex. } else { *addr = new_value; } } inline void Object::WriteBarrierField(const Object* dst, MemberOffset field_offset, const Object* new_value) { Runtime::Current()->GetHeap()->WriteBarrierField(dst, field_offset, new_value); } inline void Object::VerifyObject(const Object* obj) { if (kIsDebugBuild) { Runtime::Current()->GetHeap()->VerifyObject(obj); } } } // namespace mirror } // namespace art #endif // ART_RUNTIME_MIRROR_OBJECT_INL_H_