ART: Move DexCache arrays to native.
This CL has a companion CL in libcore/
https://android-review.googlesource.com/162985
Change-Id: Icbc9e20ad1b565e603195b12714762bb446515fa
diff --git a/runtime/art_method-inl.h b/runtime/art_method-inl.h
index d38cc56..cfd7fcd 100644
--- a/runtime/art_method-inl.h
+++ b/runtime/art_method-inl.h
@@ -22,11 +22,12 @@
#include "art_field.h"
#include "base/logging.h"
#include "class_linker-inl.h"
+#include "common_throws.h"
#include "dex_file.h"
#include "dex_file-inl.h"
#include "gc_root-inl.h"
#include "mirror/class-inl.h"
-#include "mirror/dex_cache.h"
+#include "mirror/dex_cache-inl.h"
#include "mirror/object-inl.h"
#include "mirror/object_array.h"
#include "oat.h"
@@ -95,14 +96,20 @@
return dex_method_index_;
}
-inline mirror::PointerArray* ArtMethod::GetDexCacheResolvedMethods() {
- GcRootSource gc_root_source(this);
- return dex_cache_resolved_methods_.Read(&gc_root_source);
+inline ArtMethod** ArtMethod::GetDexCacheResolvedMethods(size_t pointer_size) {
+ return GetNativePointer<ArtMethod**>(DexCacheResolvedMethodsOffset(pointer_size),
+ pointer_size);
}
inline ArtMethod* ArtMethod::GetDexCacheResolvedMethod(uint16_t method_index, size_t ptr_size) {
- auto* method = GetDexCacheResolvedMethods()->GetElementPtrSize<ArtMethod*>(
- method_index, ptr_size);
+ // NOTE: Unchecked, i.e. not throwing AIOOB. We don't even know the length here
+ // without accessing the DexCache and we don't want to do that in release build.
+ DCHECK_LT(method_index,
+ GetInterfaceMethodIfProxy(ptr_size)->GetDeclaringClass()
+ ->GetDexCache()->NumResolvedMethods());
+ ArtMethod* method = mirror::DexCache::GetElementPtrSize(GetDexCacheResolvedMethods(ptr_size),
+ method_index,
+ ptr_size);
if (LIKELY(method != nullptr)) {
auto* declaring_class = method->GetDeclaringClass();
if (LIKELY(declaring_class == nullptr || !declaring_class->IsErroneous())) {
@@ -112,52 +119,70 @@
return nullptr;
}
-inline void ArtMethod::SetDexCacheResolvedMethod(uint16_t method_idx, ArtMethod* new_method,
+inline void ArtMethod::SetDexCacheResolvedMethod(uint16_t method_index, ArtMethod* new_method,
size_t ptr_size) {
+ // NOTE: Unchecked, i.e. not throwing AIOOB. We don't even know the length here
+ // without accessing the DexCache and we don't want to do that in release build.
+ DCHECK_LT(method_index,
+ GetInterfaceMethodIfProxy(ptr_size)->GetDeclaringClass()
+ ->GetDexCache()->NumResolvedMethods());
DCHECK(new_method == nullptr || new_method->GetDeclaringClass() != nullptr);
- GetDexCacheResolvedMethods()->SetElementPtrSize(method_idx, new_method, ptr_size);
+ mirror::DexCache::SetElementPtrSize(GetDexCacheResolvedMethods(ptr_size),
+ method_index,
+ new_method,
+ ptr_size);
}
-inline bool ArtMethod::HasDexCacheResolvedMethods() {
- return GetDexCacheResolvedMethods() != nullptr;
+inline bool ArtMethod::HasDexCacheResolvedMethods(size_t pointer_size) {
+ return GetDexCacheResolvedMethods(pointer_size) != nullptr;
}
-inline bool ArtMethod::HasSameDexCacheResolvedMethods(mirror::PointerArray* other_cache) {
- return GetDexCacheResolvedMethods() == other_cache;
+inline bool ArtMethod::HasSameDexCacheResolvedMethods(ArtMethod** other_cache,
+ size_t pointer_size) {
+ return GetDexCacheResolvedMethods(pointer_size) == other_cache;
}
-inline bool ArtMethod::HasSameDexCacheResolvedMethods(ArtMethod* other) {
- return GetDexCacheResolvedMethods() == other->GetDexCacheResolvedMethods();
+inline bool ArtMethod::HasSameDexCacheResolvedMethods(ArtMethod* other, size_t pointer_size) {
+ return GetDexCacheResolvedMethods(pointer_size) ==
+ other->GetDexCacheResolvedMethods(pointer_size);
}
-inline mirror::ObjectArray<mirror::Class>* ArtMethod::GetDexCacheResolvedTypes() {
- GcRootSource gc_root_source(this);
- return dex_cache_resolved_types_.Read(&gc_root_source);
+inline GcRoot<mirror::Class>* ArtMethod::GetDexCacheResolvedTypes(size_t pointer_size) {
+ return GetNativePointer<GcRoot<mirror::Class>*>(DexCacheResolvedTypesOffset(pointer_size),
+ pointer_size);
}
template <bool kWithCheck>
-inline mirror::Class* ArtMethod::GetDexCacheResolvedType(uint32_t type_index) {
- mirror::Class* klass = kWithCheck ?
- GetDexCacheResolvedTypes()->Get(type_index) :
- GetDexCacheResolvedTypes()->GetWithoutChecks(type_index);
+inline mirror::Class* ArtMethod::GetDexCacheResolvedType(uint32_t type_index, size_t ptr_size) {
+ if (kWithCheck) {
+ mirror::DexCache* dex_cache =
+ GetInterfaceMethodIfProxy(ptr_size)->GetDeclaringClass()->GetDexCache();
+ if (UNLIKELY(type_index >= dex_cache->NumResolvedTypes())) {
+ ThrowArrayIndexOutOfBoundsException(type_index, dex_cache->NumResolvedTypes());
+ return nullptr;
+ }
+ }
+ mirror::Class* klass = GetDexCacheResolvedTypes(ptr_size)[type_index].Read();
return (klass != nullptr && !klass->IsErroneous()) ? klass : nullptr;
}
-inline bool ArtMethod::HasDexCacheResolvedTypes() {
- return GetDexCacheResolvedTypes() != nullptr;
+inline bool ArtMethod::HasDexCacheResolvedTypes(size_t pointer_size) {
+ return GetDexCacheResolvedTypes(pointer_size) != nullptr;
}
-inline bool ArtMethod::HasSameDexCacheResolvedTypes(
- mirror::ObjectArray<mirror::Class>* other_cache) {
- return GetDexCacheResolvedTypes() == other_cache;
+inline bool ArtMethod::HasSameDexCacheResolvedTypes(GcRoot<mirror::Class>* other_cache,
+ size_t pointer_size) {
+ return GetDexCacheResolvedTypes(pointer_size) == other_cache;
}
-inline bool ArtMethod::HasSameDexCacheResolvedTypes(ArtMethod* other) {
- return GetDexCacheResolvedTypes() == other->GetDexCacheResolvedTypes();
+inline bool ArtMethod::HasSameDexCacheResolvedTypes(ArtMethod* other, size_t pointer_size) {
+ return GetDexCacheResolvedTypes(pointer_size) == other->GetDexCacheResolvedTypes(pointer_size);
}
-inline mirror::Class* ArtMethod::GetClassFromTypeIndex(uint16_t type_idx, bool resolve) {
- mirror::Class* type = GetDexCacheResolvedType(type_idx);
+inline mirror::Class* ArtMethod::GetClassFromTypeIndex(uint16_t type_idx,
+ bool resolve,
+ size_t ptr_size) {
+ mirror::Class* type = GetDexCacheResolvedType(type_idx, ptr_size);
if (type == nullptr && resolve) {
type = Runtime::Current()->GetClassLinker()->ResolveType(type_idx, this);
CHECK(type != nullptr || Thread::Current()->IsExceptionPending());
@@ -391,9 +416,9 @@
return GetDeclaringClass()->GetDexFile().GetCodeItem(GetCodeItemOffset());
}
-inline bool ArtMethod::IsResolvedTypeIdx(uint16_t type_idx) {
+inline bool ArtMethod::IsResolvedTypeIdx(uint16_t type_idx, size_t ptr_size) {
DCHECK(!IsProxyMethod());
- return GetDexCacheResolvedType(type_idx) != nullptr;
+ return GetDexCacheResolvedType(type_idx, ptr_size) != nullptr;
}
inline int32_t ArtMethod::GetLineNumFromDexPC(uint32_t dex_pc) {
@@ -467,30 +492,33 @@
return this;
}
mirror::Class* klass = GetDeclaringClass();
- auto interface_method = GetDexCacheResolvedMethods()->GetElementPtrSize<ArtMethod*>(
- GetDexMethodIndex(), pointer_size);
+ ArtMethod* interface_method = mirror::DexCache::GetElementPtrSize(
+ GetDexCacheResolvedMethods(pointer_size),
+ GetDexMethodIndex(),
+ pointer_size);
DCHECK(interface_method != nullptr);
DCHECK_EQ(interface_method,
Runtime::Current()->GetClassLinker()->FindMethodForProxy(klass, this));
return interface_method;
}
-inline void ArtMethod::SetDexCacheResolvedMethods(mirror::PointerArray* new_dex_cache_methods) {
- dex_cache_resolved_methods_ = GcRoot<mirror::PointerArray>(new_dex_cache_methods);
+inline void ArtMethod::SetDexCacheResolvedMethods(ArtMethod** new_dex_cache_methods,
+ size_t ptr_size) {
+ SetNativePointer(DexCacheResolvedMethodsOffset(ptr_size), new_dex_cache_methods, ptr_size);
}
-inline void ArtMethod::SetDexCacheResolvedTypes(
- mirror::ObjectArray<mirror::Class>* new_dex_cache_types) {
- dex_cache_resolved_types_ = GcRoot<mirror::ObjectArray<mirror::Class>>(new_dex_cache_types);
+inline void ArtMethod::SetDexCacheResolvedTypes(GcRoot<mirror::Class>* new_dex_cache_types,
+ size_t ptr_size) {
+ SetNativePointer(DexCacheResolvedTypesOffset(ptr_size), new_dex_cache_types, ptr_size);
}
-inline mirror::Class* ArtMethod::GetReturnType(bool resolve) {
+inline mirror::Class* ArtMethod::GetReturnType(bool resolve, size_t ptr_size) {
DCHECK(!IsProxyMethod());
const DexFile* dex_file = GetDexFile();
const DexFile::MethodId& method_id = dex_file->GetMethodId(GetDexMethodIndex());
const DexFile::ProtoId& proto_id = dex_file->GetMethodPrototype(method_id);
uint16_t return_type_idx = proto_id.return_type_idx_;
- mirror::Class* type = GetDexCacheResolvedType(return_type_idx);
+ mirror::Class* type = GetDexCacheResolvedType(return_type_idx, ptr_size);
if (type == nullptr && resolve) {
type = Runtime::Current()->GetClassLinker()->ResolveType(return_type_idx, this);
CHECK(type != nullptr || Thread::Current()->IsExceptionPending());
@@ -500,19 +528,29 @@
template<typename RootVisitorType>
void ArtMethod::VisitRoots(RootVisitorType& visitor) {
+ ArtMethod* interface_method = nullptr;
+ mirror::Class* klass = declaring_class_.Read();
+ if (UNLIKELY(klass != nullptr && klass->IsProxyClass())) {
+ // For normal methods, dex cache shortcuts will be visited through the declaring class.
+ // However, for proxies we need to keep the interface method alive, so we visit its roots.
+ size_t pointer_size = Runtime::Current()->GetClassLinker()->GetImagePointerSize();
+ interface_method = mirror::DexCache::GetElementPtrSize(
+ GetDexCacheResolvedMethods(pointer_size),
+ GetDexMethodIndex(),
+ pointer_size);
+ DCHECK(interface_method != nullptr);
+ DCHECK_EQ(interface_method,
+ Runtime::Current()->GetClassLinker()->FindMethodForProxy(klass, this));
+ interface_method->VisitRoots(visitor);
+ }
+
visitor.VisitRootIfNonNull(declaring_class_.AddressWithoutBarrier());
- visitor.VisitRootIfNonNull(dex_cache_resolved_methods_.AddressWithoutBarrier());
- visitor.VisitRootIfNonNull(dex_cache_resolved_types_.AddressWithoutBarrier());
}
inline void ArtMethod::CopyFrom(const ArtMethod* src, size_t image_pointer_size) {
memcpy(reinterpret_cast<void*>(this), reinterpret_cast<const void*>(src),
Size(image_pointer_size));
declaring_class_ = GcRoot<mirror::Class>(const_cast<ArtMethod*>(src)->GetDeclaringClass());
- dex_cache_resolved_methods_ = GcRoot<mirror::PointerArray>(
- const_cast<ArtMethod*>(src)->GetDexCacheResolvedMethods());
- dex_cache_resolved_types_ = GcRoot<mirror::ObjectArray<mirror::Class>>(
- const_cast<ArtMethod*>(src)->GetDexCacheResolvedTypes());
}
} // namespace art