Tidy MethodProtoHelper.
Move to place of only use, class_linker.cc. Be lazy in computing the name.
Change-Id: I1438efbda58369ddd0ac36eda8a5a0a6c6fdff77
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index f01f2c6..a6ff530 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -4610,6 +4610,49 @@
return LinkInterfaceMethods(self, klass, interfaces, out_imt); // Link interface method last.
}
+// Comparator for name and signature of a method, used in finding overriding methods. Implementation
+// avoids the use of handles, if it didn't then rather than compare dex files we could compare dex
+// caches in the implementation below.
+class MethodNameAndSignatureComparator FINAL : public ValueObject {
+ public:
+ explicit MethodNameAndSignatureComparator(mirror::ArtMethod* method)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) :
+ dex_file_(method->GetDexFile()), mid_(&dex_file_->GetMethodId(method->GetDexMethodIndex())),
+ name_(nullptr), name_len_(0) {
+ DCHECK(!method->IsProxyMethod()) << PrettyMethod(method);
+ }
+
+ bool HasSameNameAndSignature(mirror::ArtMethod* other)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ DCHECK(!other->IsProxyMethod()) << PrettyMethod(other);
+ const DexFile* other_dex_file = other->GetDexFile();
+ const DexFile::MethodId& other_mid = other_dex_file->GetMethodId(other->GetDexMethodIndex());
+ if (dex_file_ == other_dex_file) {
+ return mid_->name_idx_ == other_mid.name_idx_ && mid_->proto_idx_ == other_mid.proto_idx_;
+ }
+ if (name_ == nullptr) {
+ name_ = dex_file_->StringDataAndUtf16LengthByIdx(mid_->name_idx_, &name_len_);
+ }
+ uint32_t other_name_len;
+ const char* other_name = other_dex_file->StringDataAndUtf16LengthByIdx(other_mid.name_idx_,
+ &other_name_len);
+ if (name_len_ != other_name_len || strcmp(name_, other_name) != 0) {
+ return false;
+ }
+ return dex_file_->GetMethodSignature(*mid_) == other_dex_file->GetMethodSignature(other_mid);
+ }
+
+ private:
+ // Dex file for the method to compare against.
+ const DexFile* const dex_file_;
+ // MethodId for the method to compare against.
+ const DexFile::MethodId* const mid_;
+ // Lazily computed name from the dex file's strings.
+ const char* name_;
+ // Lazily computed name length.
+ uint32_t name_len_;
+};
+
bool ClassLinker::LinkVirtualMethods(Thread* self, Handle<mirror::Class> klass) {
const size_t num_virtual_methods = klass->NumVirtualMethods();
if (klass->HasSuperClass()) {
@@ -4640,12 +4683,15 @@
// See if any of our virtual methods override the superclass.
for (size_t i = 0; i < num_virtual_methods; ++i) {
mirror::ArtMethod* local_method = klass->GetVirtualMethodDuringLinking(i);
- MethodProtoHelper local_helper(local_method);
+ MethodNameAndSignatureComparator
+ virtual_method_name_comparator(local_method->GetInterfaceMethodIfProxy());
size_t j = 0;
for (; j < actual_count; ++j) {
mirror::ArtMethod* super_method = vtable->GetWithoutChecks(j);
- MethodProtoHelper super_helper(super_method);
- if (local_helper.HasSameNameAndSignature(super_helper)) {
+ if (super_method->GetDeclaringClass() == klass.Get()) {
+ continue; // A previously overridden method.
+ }
+ if (virtual_method_name_comparator.HasSameNameAndSignature(super_method)) {
if (klass->CanAccessMember(super_method->GetDeclaringClass(),
super_method->GetAccessFlags())) {
if (super_method->IsFinal()) {
@@ -4903,7 +4949,7 @@
}
for (size_t j = 0; j < num_methods; ++j) {
mirror::ArtMethod* interface_method = iftable->GetInterface(i)->GetVirtualMethod(j);
- MethodProtoHelper interface_helper(interface_method);
+ MethodNameAndSignatureComparator interface_name_comparator(interface_method);
int32_t k;
// For each method listed in the interface's method list, find the
// matching method in our class's method list. We want to favor the
@@ -4915,8 +4961,10 @@
// matter which direction we go. We walk it backward anyway.)
for (k = input_array->GetLength() - 1; k >= 0; --k) {
mirror::ArtMethod* vtable_method = input_array->GetWithoutChecks(k);
- MethodProtoHelper vtable_helper(vtable_method);
- if (interface_helper.HasSameNameAndSignature(vtable_helper)) {
+ mirror::ArtMethod* vtable_method_for_name_comparison =
+ vtable_method->GetInterfaceMethodIfProxy();
+ if (interface_name_comparator.HasSameNameAndSignature(
+ vtable_method_for_name_comparison)) {
if (!vtable_method->IsAbstract() && !vtable_method->IsPublic()) {
ThrowIllegalAccessError(
klass.Get(),
@@ -4935,7 +4983,10 @@
} else if (imt_ref != conflict_method) {
// If we are not a conflict and we have the same signature and name as the imt entry,
// it must be that we overwrote a superclass vtable entry.
- if (MethodProtoHelper(imt_ref).HasSameNameAndSignature(vtable_helper)) {
+ MethodNameAndSignatureComparator
+ imt_ref_name_comparator(imt_ref->GetInterfaceMethodIfProxy());
+ if (imt_ref_name_comparator.HasSameNameAndSignature(
+ vtable_method_for_name_comparison)) {
out_imt->SetReference(imt_index, vtable_method);
} else {
out_imt->SetReference(imt_index, conflict_method);
@@ -4948,8 +4999,7 @@
mirror::ArtMethod* miranda_method = nullptr;
for (size_t l = 0; l < miranda_list_size; ++l) {
mirror::ArtMethod* mir_method = miranda_list->Get(l);
- MethodProtoHelper vtable_helper(mir_method);
- if (interface_helper.HasSameNameAndSignature(vtable_helper)) {
+ if (interface_name_comparator.HasSameNameAndSignature(mir_method)) {
miranda_method = mir_method;
break;
}
diff --git a/runtime/dex_file.h b/runtime/dex_file.h
index 620bd6e..10fe6bf 100644
--- a/runtime/dex_file.h
+++ b/runtime/dex_file.h
@@ -24,6 +24,7 @@
#include "base/logging.h"
#include "base/mutex.h" // For Locks::mutator_lock_.
+#include "base/value_object.h"
#include "globals.h"
#include "invoke_type.h"
#include "jni.h"
@@ -1027,7 +1028,7 @@
};
// Abstract the signature of a method.
-class Signature {
+class Signature : public ValueObject {
public:
std::string ToString() const;
diff --git a/runtime/method_helper-inl.h b/runtime/method_helper-inl.h
index 21cc67c..143f4bc 100644
--- a/runtime/method_helper-inl.h
+++ b/runtime/method_helper-inl.h
@@ -80,23 +80,6 @@
return s;
}
-inline MethodProtoHelper::MethodProtoHelper(mirror::ArtMethod* method) {
- method = method->GetInterfaceMethodIfProxy();
- dex_file_ = method->GetDexFile();
- mid_ = &dex_file_->GetMethodId(method->GetDexMethodIndex());
- name_ = dex_file_->StringDataAndUtf16LengthByIdx(mid_->name_idx_, &name_len_);
-}
-
-inline bool MethodProtoHelper::HasSameNameAndSignature(const MethodProtoHelper& other) const {
- if (name_len_ != other.name_len_ || strcmp(name_, other.name_) != 0) {
- return false;
- }
- if (dex_file_ == other.dex_file_) {
- return mid_->name_idx_ == other.mid_->name_idx_ && mid_->proto_idx_ == other.mid_->proto_idx_;
- }
- return dex_file_->GetMethodSignature(*mid_) == other.dex_file_->GetMethodSignature(*other.mid_);
-}
-
} // namespace art
#endif // ART_RUNTIME_METHOD_HELPER_INL_H_
diff --git a/runtime/method_helper.h b/runtime/method_helper.h
index 913b41b..fe364d3 100644
--- a/runtime/method_helper.h
+++ b/runtime/method_helper.h
@@ -24,19 +24,6 @@
namespace art {
-class MethodProtoHelper {
- public:
- ALWAYS_INLINE MethodProtoHelper(mirror::ArtMethod* method)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- ALWAYS_INLINE bool HasSameNameAndSignature(const MethodProtoHelper& other) const;
-
- private:
- const DexFile* dex_file_;
- const DexFile::MethodId* mid_;
- const char* name_;
- uint32_t name_len_;
-};
-
template <template <class T> class HandleKind>
class MethodHelperT {
public:
diff --git a/runtime/mirror/art_method-inl.h b/runtime/mirror/art_method-inl.h
index cb6ac4f..a0b6adf 100644
--- a/runtime/mirror/art_method-inl.h
+++ b/runtime/mirror/art_method-inl.h
@@ -436,11 +436,15 @@
return GetInterfaceMethodIfProxy()->GetDeclaringClass()->GetDexCache();
}
+inline bool ArtMethod::IsProxyMethod() {
+ return GetDeclaringClass()->IsProxyClass();
+}
+
inline ArtMethod* ArtMethod::GetInterfaceMethodIfProxy() {
- mirror::Class* klass = GetDeclaringClass();
- if (LIKELY(!klass->IsProxyClass())) {
+ if (LIKELY(!IsProxyMethod())) {
return this;
}
+ mirror::Class* klass = GetDeclaringClass();
mirror::ArtMethod* interface_method = GetDexCacheResolvedMethods()->Get(GetDexMethodIndex());
DCHECK(interface_method != nullptr);
DCHECK_EQ(interface_method,
diff --git a/runtime/mirror/art_method.cc b/runtime/mirror/art_method.cc
index 014d1a9..ddc16fb 100644
--- a/runtime/mirror/art_method.cc
+++ b/runtime/mirror/art_method.cc
@@ -105,10 +105,6 @@
return num_registers;
}
-bool ArtMethod::IsProxyMethod() {
- return GetDeclaringClass()->IsProxyClass();
-}
-
ArtMethod* ArtMethod::FindOverriddenMethod() {
if (IsStatic()) {
return NULL;
diff --git a/runtime/mirror/class.h b/runtime/mirror/class.h
index 6a7faaa..d9094fc 100644
--- a/runtime/mirror/class.h
+++ b/runtime/mirror/class.h
@@ -1147,11 +1147,11 @@
// The following data exist in real class objects.
// Embedded Imtable, for class object that's not an interface, fixed size.
- ImTableEntry embedded_imtable_[0];
+ // ImTableEntry embedded_imtable_[0];
// Embedded Vtable, for class object that's not an interface, variable size.
- VTableEntry embedded_vtable_[0];
+ // VTableEntry embedded_vtable_[0];
// Static fields, variable size.
- uint32_t fields_[0];
+ // uint32_t fields_[0];
// java.lang.Class
static GcRoot<Class> java_lang_Class_;