|  | /* | 
|  | * 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_CLASS_INL_H_ | 
|  | #define ART_RUNTIME_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_RUNTIME_MIRROR_CLASS_INL_H_ |