summaryrefslogtreecommitdiffstats
path: root/runtime/mirror/class-inl.h
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/mirror/class-inl.h')
-rw-r--r--runtime/mirror/class-inl.h349
1 files changed, 349 insertions, 0 deletions
diff --git a/runtime/mirror/class-inl.h b/runtime/mirror/class-inl.h
new file mode 100644
index 0000000..6819fb2
--- /dev/null
+++ b/runtime/mirror/class-inl.h
@@ -0,0 +1,349 @@
+/*
+ * 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_SRC_MIRROR_CLASS_INL_H_
+#define ART_SRC_MIRROR_CLASS_INL_H_
+
+#include "class.h"
+
+#include "abstract_method.h"
+#include "class_loader.h"
+#include "dex_cache.h"
+#include "field.h"
+#include "iftable.h"
+#include "object_array-inl.h"
+#include "runtime.h"
+#include "string.h"
+
+namespace art {
+namespace mirror {
+
+inline size_t Class::GetObjectSize() const {
+ DCHECK(!IsVariableSize()) << " class=" << PrettyTypeOf(this);
+ DCHECK_EQ(sizeof(size_t), sizeof(int32_t));
+ size_t result = GetField32(OFFSET_OF_OBJECT_MEMBER(Class, object_size_), false);
+ DCHECK_GE(result, sizeof(Object)) << " class=" << PrettyTypeOf(this);
+ return result;
+}
+
+inline Class* Class::GetSuperClass() const {
+ // Can only get super class for loaded classes (hack for when runtime is
+ // initializing)
+ DCHECK(IsLoaded() || !Runtime::Current()->IsStarted()) << IsLoaded();
+ return GetFieldObject<Class*>(OFFSET_OF_OBJECT_MEMBER(Class, super_class_), false);
+}
+
+inline ClassLoader* Class::GetClassLoader() const {
+ return GetFieldObject<ClassLoader*>(OFFSET_OF_OBJECT_MEMBER(Class, class_loader_), false);
+}
+
+inline DexCache* Class::GetDexCache() const {
+ return GetFieldObject<DexCache*>(OFFSET_OF_OBJECT_MEMBER(Class, dex_cache_), false);
+}
+
+inline ObjectArray<AbstractMethod>* Class::GetDirectMethods() const {
+ DCHECK(IsLoaded() || IsErroneous());
+ return GetFieldObject<ObjectArray<AbstractMethod>*>(
+ OFFSET_OF_OBJECT_MEMBER(Class, direct_methods_), false);
+}
+
+inline void Class::SetDirectMethods(ObjectArray<AbstractMethod>* new_direct_methods)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ DCHECK(NULL == GetFieldObject<ObjectArray<AbstractMethod>*>(
+ OFFSET_OF_OBJECT_MEMBER(Class, direct_methods_), false));
+ DCHECK_NE(0, new_direct_methods->GetLength());
+ SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Class, direct_methods_),
+ new_direct_methods, false);
+}
+
+inline AbstractMethod* Class::GetDirectMethod(int32_t i) const
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ return GetDirectMethods()->Get(i);
+}
+
+inline void Class::SetDirectMethod(uint32_t i, AbstractMethod* f) // TODO: uint16_t
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_){
+ ObjectArray<AbstractMethod>* direct_methods =
+ GetFieldObject<ObjectArray<AbstractMethod>*>(
+ OFFSET_OF_OBJECT_MEMBER(Class, direct_methods_), false);
+ direct_methods->Set(i, f);
+}
+
+// Returns the number of static, private, and constructor methods.
+inline size_t Class::NumDirectMethods() const {
+ return (GetDirectMethods() != NULL) ? GetDirectMethods()->GetLength() : 0;
+}
+
+inline ObjectArray<AbstractMethod>* Class::GetVirtualMethods() const {
+ DCHECK(IsLoaded() || IsErroneous());
+ return GetFieldObject<ObjectArray<AbstractMethod>*>(
+ OFFSET_OF_OBJECT_MEMBER(Class, virtual_methods_), false);
+}
+
+inline void Class::SetVirtualMethods(ObjectArray<AbstractMethod>* new_virtual_methods) {
+ // TODO: we reassign virtual methods to grow the table for miranda
+ // methods.. they should really just be assigned once
+ DCHECK_NE(0, new_virtual_methods->GetLength());
+ SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Class, virtual_methods_),
+ new_virtual_methods, false);
+}
+
+inline size_t Class::NumVirtualMethods() const {
+ return (GetVirtualMethods() != NULL) ? GetVirtualMethods()->GetLength() : 0;
+}
+
+inline AbstractMethod* Class::GetVirtualMethod(uint32_t i) const
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ DCHECK(IsResolved() || IsErroneous());
+ return GetVirtualMethods()->Get(i);
+}
+
+inline AbstractMethod* Class::GetVirtualMethodDuringLinking(uint32_t i) const
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ DCHECK(IsLoaded() || IsErroneous());
+ return GetVirtualMethods()->Get(i);
+}
+
+inline void Class::SetVirtualMethod(uint32_t i, AbstractMethod* f) // TODO: uint16_t
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ ObjectArray<AbstractMethod>* virtual_methods =
+ GetFieldObject<ObjectArray<AbstractMethod>*>(
+ OFFSET_OF_OBJECT_MEMBER(Class, virtual_methods_), false);
+ virtual_methods->Set(i, f);
+}
+
+inline ObjectArray<AbstractMethod>* Class::GetVTable() const {
+ DCHECK(IsResolved() || IsErroneous());
+ return GetFieldObject<ObjectArray<AbstractMethod>*>(OFFSET_OF_OBJECT_MEMBER(Class, vtable_), false);
+}
+
+inline ObjectArray<AbstractMethod>* Class::GetVTableDuringLinking() const {
+ DCHECK(IsLoaded() || IsErroneous());
+ return GetFieldObject<ObjectArray<AbstractMethod>*>(OFFSET_OF_OBJECT_MEMBER(Class, vtable_), false);
+}
+
+inline void Class::SetVTable(ObjectArray<AbstractMethod>* new_vtable)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Class, vtable_), new_vtable, false);
+}
+
+inline bool Class::Implements(const Class* klass) const {
+ DCHECK(klass != NULL);
+ DCHECK(klass->IsInterface()) << PrettyClass(this);
+ // All interfaces implemented directly and by our superclass, and
+ // recursively all super-interfaces of those interfaces, are listed
+ // in iftable_, so we can just do a linear scan through that.
+ int32_t iftable_count = GetIfTableCount();
+ IfTable* iftable = GetIfTable();
+ for (int32_t i = 0; i < iftable_count; i++) {
+ if (iftable->GetInterface(i) == klass) {
+ return true;
+ }
+ }
+ return false;
+}
+
+// Determine whether "this" is assignable from "src", where both of these
+// are array classes.
+//
+// Consider an array class, e.g. Y[][], where Y is a subclass of X.
+// Y[][] = Y[][] --> true (identity)
+// X[][] = Y[][] --> true (element superclass)
+// Y = Y[][] --> false
+// Y[] = Y[][] --> false
+// Object = Y[][] --> true (everything is an object)
+// Object[] = Y[][] --> true
+// Object[][] = Y[][] --> true
+// Object[][][] = Y[][] --> false (too many []s)
+// Serializable = Y[][] --> true (all arrays are Serializable)
+// Serializable[] = Y[][] --> true
+// Serializable[][] = Y[][] --> false (unless Y is Serializable)
+//
+// Don't forget about primitive types.
+// Object[] = int[] --> false
+//
+inline bool Class::IsArrayAssignableFromArray(const Class* src) const {
+ DCHECK(IsArrayClass()) << PrettyClass(this);
+ DCHECK(src->IsArrayClass()) << PrettyClass(src);
+ return GetComponentType()->IsAssignableFrom(src->GetComponentType());
+}
+
+inline bool Class::IsAssignableFromArray(const Class* src) const {
+ DCHECK(!IsInterface()) << PrettyClass(this); // handled first in IsAssignableFrom
+ DCHECK(src->IsArrayClass()) << PrettyClass(src);
+ if (!IsArrayClass()) {
+ // If "this" is not also an array, it must be Object.
+ // src's super should be java_lang_Object, since it is an array.
+ Class* java_lang_Object = src->GetSuperClass();
+ DCHECK(java_lang_Object != NULL) << PrettyClass(src);
+ DCHECK(java_lang_Object->GetSuperClass() == NULL) << PrettyClass(src);
+ return this == java_lang_Object;
+ }
+ return IsArrayAssignableFromArray(src);
+}
+
+inline bool Class::IsSubClass(const Class* klass) const {
+ DCHECK(!IsInterface()) << PrettyClass(this);
+ DCHECK(!IsArrayClass()) << PrettyClass(this);
+ const Class* current = this;
+ do {
+ if (current == klass) {
+ return true;
+ }
+ current = current->GetSuperClass();
+ } while (current != NULL);
+ return false;
+}
+
+inline AbstractMethod* Class::FindVirtualMethodForInterface(AbstractMethod* method) const {
+ Class* declaring_class = method->GetDeclaringClass();
+ DCHECK(declaring_class != NULL) << PrettyClass(this);
+ DCHECK(declaring_class->IsInterface()) << PrettyMethod(method);
+ // TODO cache to improve lookup speed
+ int32_t iftable_count = GetIfTableCount();
+ IfTable* iftable = GetIfTable();
+ for (int32_t i = 0; i < iftable_count; i++) {
+ if (iftable->GetInterface(i) == declaring_class) {
+ return iftable->GetMethodArray(i)->Get(method->GetMethodIndex());
+ }
+ }
+ return NULL;
+}
+
+inline AbstractMethod* Class::FindVirtualMethodForVirtual(AbstractMethod* method) const
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ DCHECK(!method->GetDeclaringClass()->IsInterface() || method->IsMiranda());
+ // The argument method may from a super class.
+ // Use the index to a potentially overridden one for this instance's class.
+ return GetVTable()->Get(method->GetMethodIndex());
+}
+
+inline AbstractMethod* Class::FindVirtualMethodForSuper(AbstractMethod* method) const
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ DCHECK(!method->GetDeclaringClass()->IsInterface());
+ return GetSuperClass()->GetVTable()->Get(method->GetMethodIndex());
+}
+
+inline AbstractMethod* Class::FindVirtualMethodForVirtualOrInterface(AbstractMethod* method) const {
+ if (method->IsDirect()) {
+ return method;
+ }
+ if (method->GetDeclaringClass()->IsInterface()) {
+ return FindVirtualMethodForInterface(method);
+ }
+ return FindVirtualMethodForVirtual(method);
+}
+
+inline IfTable* Class::GetIfTable() const {
+ return GetFieldObject<IfTable*>(OFFSET_OF_OBJECT_MEMBER(Class, iftable_), false);
+}
+
+inline int32_t Class::GetIfTableCount() const {
+ IfTable* iftable = GetIfTable();
+ if (iftable == NULL) {
+ return 0;
+ }
+ return iftable->Count();
+}
+
+inline void Class::SetIfTable(IfTable* new_iftable) {
+ SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Class, iftable_), new_iftable, false);
+}
+
+inline ObjectArray<Field>* Class::GetIFields() const {
+ DCHECK(IsLoaded() || IsErroneous());
+ return GetFieldObject<ObjectArray<Field>*>(OFFSET_OF_OBJECT_MEMBER(Class, ifields_), false);
+}
+
+inline void Class::SetIFields(ObjectArray<Field>* new_ifields)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ DCHECK(NULL == GetFieldObject<ObjectArray<Field>*>(
+ OFFSET_OF_OBJECT_MEMBER(Class, ifields_), false));
+ SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Class, ifields_), new_ifields, false);
+}
+
+inline ObjectArray<Field>* Class::GetSFields() const {
+ DCHECK(IsLoaded() || IsErroneous());
+ return GetFieldObject<ObjectArray<Field>*>(OFFSET_OF_OBJECT_MEMBER(Class, sfields_), false);
+}
+
+inline void Class::SetSFields(ObjectArray<Field>* new_sfields)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ DCHECK(NULL == GetFieldObject<ObjectArray<Field>*>(
+ OFFSET_OF_OBJECT_MEMBER(Class, sfields_), false));
+ SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Class, sfields_), new_sfields, false);
+}
+
+inline size_t Class::NumStaticFields() const {
+ return (GetSFields() != NULL) ? GetSFields()->GetLength() : 0;
+}
+
+inline Field* Class::GetStaticField(uint32_t i) const // TODO: uint16_t
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ return GetSFields()->Get(i);
+}
+
+inline void Class::SetStaticField(uint32_t i, Field* f) // TODO: uint16_t
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ ObjectArray<Field>* sfields= GetFieldObject<ObjectArray<Field>*>(
+ OFFSET_OF_OBJECT_MEMBER(Class, sfields_), false);
+ sfields->Set(i, f);
+}
+
+inline size_t Class::NumInstanceFields() const {
+ return (GetIFields() != NULL) ? GetIFields()->GetLength() : 0;
+}
+
+inline Field* Class::GetInstanceField(uint32_t i) const // TODO: uint16_t
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_){
+ DCHECK_NE(NumInstanceFields(), 0U);
+ return GetIFields()->Get(i);
+}
+
+inline void Class::SetInstanceField(uint32_t i, Field* f) // TODO: uint16_t
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_){
+ ObjectArray<Field>* ifields= GetFieldObject<ObjectArray<Field>*>(
+ OFFSET_OF_OBJECT_MEMBER(Class, ifields_), false);
+ ifields->Set(i, f);
+}
+
+inline void Class::SetVerifyErrorClass(Class* klass) {
+ CHECK(klass != NULL) << PrettyClass(this);
+ SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Class, verify_error_class_), klass, false);
+}
+
+inline uint32_t Class::GetAccessFlags() const {
+ // Check class is loaded or this is java.lang.String that has a
+ // circularity issue during loading the names of its members
+ DCHECK(IsLoaded() || IsErroneous() ||
+ this == String::GetJavaLangString() ||
+ this == Field::GetJavaLangReflectField() ||
+ this == AbstractMethod::GetConstructorClass() ||
+ this == AbstractMethod::GetMethodClass());
+ return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, access_flags_), false);
+}
+
+inline String* Class::GetName() const {
+ return GetFieldObject<String*>(OFFSET_OF_OBJECT_MEMBER(Class, name_), false);
+}
+inline void Class::SetName(String* name) {
+ SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Class, name_), name, false);
+}
+
+} // namespace mirror
+} // namespace art
+
+#endif // ART_SRC_MIRROR_CLASS_INL_H_