Avoid std::string allocations in HasSameNameAndSignature.

Creating a signature requires a std::string that's only used for the purpose of
a comparison. Avoid the std::string by comparing the elements of the method's
proto_ids.

Change-Id: I4394df2ac20bb5896936954f68937fad7e9f7e91
diff --git a/runtime/object_utils.h b/runtime/object_utils.h
index 6ee3016..c55e10e 100644
--- a/runtime/object_utils.h
+++ b/runtime/object_utils.h
@@ -569,16 +569,64 @@
 
   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()) {
-      const DexFile& dex_file = GetDexFile();
-      const DexFile::MethodId& mid = dex_file.GetMethodId(method_->GetDexMethodIndex());
       const DexFile::MethodId& other_mid =
           dex_file.GetMethodId(other->method_->GetDexMethodIndex());
       return mid.name_idx_ == other_mid.name_idx_ && mid.proto_idx_ == other_mid.proto_idx_;
     }
-    StringPiece name(GetName());
-    StringPiece other_name(other->GetName());
-    return name == other_name && GetSignature() == other->GetSignature();
+    const DexFile& other_dex_file = other->GetDexFile();
+    const DexFile::MethodId& other_mid =
+        other_dex_file.GetMethodId(other->method_->GetDexMethodIndex());
+    uint32_t length, other_length;
+    const char* data = dex_file.StringDataAndLengthByIdx(mid.name_idx_, &length);
+    const char* other_data = other_dex_file.StringDataAndLengthByIdx(other_mid.name_idx_,
+                                                                     &other_length);
+    if ((length != other_length) || (strcmp(data, other_data) != 0)) {
+      return false;  // Name mismatch.
+    }
+    const DexFile::ProtoId& proto_id = dex_file.GetMethodPrototype(mid);
+    const DexFile::ProtoId& other_proto_id = other_dex_file.GetMethodPrototype(other_mid);
+    data = dex_file.StringDataAndLengthByIdx(proto_id.shorty_idx_, &length);
+    other_data = dex_file.StringDataAndLengthByIdx(proto_id.shorty_idx_, &other_length);
+    if ((length != other_length) || (strcmp(data, other_data) != 0)) {
+      return false;  // Shorty mismatch.
+    }
+    const DexFile::TypeId& return_type_id = dex_file.GetTypeId(proto_id.return_type_idx_);
+    const DexFile::TypeId& other_return_type_id =
+        other_dex_file.GetTypeId(other_proto_id.return_type_idx_);
+    data = dex_file.StringDataAndLengthByIdx(return_type_id.descriptor_idx_, &length);
+    other_data = other_dex_file.StringDataAndLengthByIdx(other_return_type_id.descriptor_idx_,
+                                                         &other_length);
+    if ((length != other_length) || (strcmp(data, other_data) != 0)) {
+      return false;  // Return type mismatch.
+    }
+    const DexFile::TypeList* params = dex_file.GetProtoParameters(proto_id);
+    const DexFile::TypeList* other_params = other_dex_file.GetProtoParameters(other_proto_id);
+    if (params == nullptr) {
+      return other_params == nullptr;  // Check both lists are empty.
+    }
+    if (other_params == nullptr) {
+      return false;  // Parameter list size mismatch.
+    }
+    uint32_t params_size = params->Size();
+    uint32_t other_params_size = other_params->Size();
+    if (params_size != other_params_size) {
+      return false;  // Parameter list size mismatch.
+    }
+    for (uint32_t i = 0; i < params_size; ++i) {
+      const DexFile::TypeId& param_id = dex_file.GetTypeId(params->GetTypeItem(i).type_idx_);
+      const DexFile::TypeId& other_param_id =
+          other_dex_file.GetTypeId(other_params->GetTypeItem(i).type_idx_);
+      data = dex_file.StringDataAndLengthByIdx(param_id.descriptor_idx_, &length);
+      other_data = other_dex_file.StringDataAndLengthByIdx(other_param_id.descriptor_idx_,
+                                                     &other_length);
+      if ((length != other_length) || (strcmp(data, other_data) != 0)) {
+        return false;  // Parameter type mismatch.
+      }
+    }
+    return true;
   }
 
   const DexFile::CodeItem* GetCodeItem()