Optimize string comparisons in Class::FindClassMethod.
The method is relatively hot in non-quickend code.
Avoid full string comparisons by comparing the unicode lengths first.
Test: ./art/test.py -b -r --interpreter --host --64
Change-Id: Ib0aa7008ca36e3916967fe082948d16823b93e02
diff --git a/libdexfile/dex/dex_file-inl.h b/libdexfile/dex/dex_file-inl.h
index eae7efc..c884eee 100644
--- a/libdexfile/dex/dex_file-inl.h
+++ b/libdexfile/dex/dex_file-inl.h
@@ -110,6 +110,14 @@
return StringDataByIdx(method_id.name_idx_);
}
+inline const char* DexFile::GetMethodName(const MethodId& method_id, uint32_t* utf_length) const {
+ return StringDataAndUtf16LengthByIdx(method_id.name_idx_, utf_length);
+}
+
+inline const char* DexFile::GetMethodName(uint32_t idx, uint32_t* utf_length) const {
+ return StringDataAndUtf16LengthByIdx(GetMethodId(idx).name_idx_, utf_length);
+}
+
inline const char* DexFile::GetMethodShorty(uint32_t idx) const {
return StringDataByIdx(GetProtoId(GetMethodId(idx).proto_idx_).shorty_idx_);
}
diff --git a/libdexfile/dex/dex_file.h b/libdexfile/dex/dex_file.h
index 6a52f67..b3e7ad4 100644
--- a/libdexfile/dex/dex_file.h
+++ b/libdexfile/dex/dex_file.h
@@ -641,6 +641,8 @@
// Returns the name of a method id.
const char* GetMethodName(const MethodId& method_id) const;
+ const char* GetMethodName(const MethodId& method_id, uint32_t* utf_length) const;
+ const char* GetMethodName(uint32_t idx, uint32_t* utf_length) const;
// Returns the shorty of a method by its index.
const char* GetMethodShorty(uint32_t idx) const;
diff --git a/runtime/mirror/class.cc b/runtime/mirror/class.cc
index e655052..e33e407 100644
--- a/runtime/mirror/class.cc
+++ b/runtime/mirror/class.cc
@@ -630,9 +630,14 @@
// If we do not have a dex_cache match, try to find the declared method in this class now.
if (this_dex_cache != dex_cache && !GetDeclaredMethodsSlice(pointer_size).empty()) {
DCHECK(name.empty());
- name = dex_file.StringDataByIdx(method_id.name_idx_);
+ // Avoid string comparisons by comparing the respective unicode lengths first.
+ uint32_t length, other_length; // UTF16 length.
+ name = dex_file.GetMethodName(method_id, &length);
for (ArtMethod& method : GetDeclaredMethodsSlice(pointer_size)) {
- if (method.GetName() == name && method.GetSignature() == signature) {
+ DCHECK_NE(method.GetDexMethodIndex(), dex::kDexNoIndex);
+ const char* other_name = method.GetDexFile()->GetMethodName(
+ method.GetDexMethodIndex(), &other_length);
+ if (length == other_length && name == other_name && signature == method.GetSignature()) {
return &method;
}
}