Improve ValidateSuperClassDescriptors performance.
ValidateSuperClassDescriptors uses FindClass with the 2 class loaders that are
being used in validating method parameter types. The use of 2 class loaders
ensures at least one miss with LookupClass and thereby a call to
ClassLoader.loadClass which will then defer to the parent class loader eating
time. This change modifies the behavior to instead lookup types with a dex
cache, so that resolution and load class are only performed once per type.
Bug: 12804658
Change-Id: Ia7be1f7bab8175a6934fd59fc54e0829beed0198
diff --git a/runtime/object_utils.h b/runtime/object_utils.h
index 072f074..504537a 100644
--- a/runtime/object_utils.h
+++ b/runtime/object_utils.h
@@ -520,8 +520,7 @@
return GetParamPrimitiveType(param) == Primitive::kPrimNot;
}
- bool HasSameNameAndSignature(MethodHelper* other)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ bool HasSameNameAndSignature(MethodHelper* other) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
const DexFile& dex_file = GetDexFile();
const DexFile::MethodId& mid = dex_file.GetMethodId(method_->GetDexMethodIndex());
if (GetDexCache() == other->GetDexCache()) {
@@ -539,6 +538,33 @@
return dex_file.GetMethodSignature(mid) == other_dex_file.GetMethodSignature(other_mid);
}
+ bool HasSameSignatureWithDifferentClassLoaders(MethodHelper* other)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ if (UNLIKELY(GetReturnType() != other->GetReturnType())) {
+ return false;
+ }
+ const DexFile::TypeList* types = GetParameterTypeList();
+ const DexFile::TypeList* other_types = other->GetParameterTypeList();
+ if (types == nullptr) {
+ return (other_types == nullptr) || (other_types->Size() == 0);
+ } else if (UNLIKELY(other_types == nullptr)) {
+ return types->Size() == 0;
+ }
+ uint32_t num_types = types->Size();
+ if (UNLIKELY(num_types != other_types->Size())) {
+ return false;
+ }
+ for (uint32_t i = 0; i < num_types; ++i) {
+ mirror::Class* param_type = GetClassFromTypeIdx(types->GetTypeItem(i).type_idx_);
+ mirror::Class* other_param_type =
+ other->GetClassFromTypeIdx(other_types->GetTypeItem(i).type_idx_);
+ if (UNLIKELY(param_type != other_param_type)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
const DexFile::CodeItem* GetCodeItem()
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return GetDexFile().GetCodeItem(method_->GetCodeItemOffset());