Refactor testing to use dex file find routines.

Change-Id: I0abdbd06c7666f23490241984e4d4340d398e18b
diff --git a/src/class_linker_test.cc b/src/class_linker_test.cc
index 5448a51..e64131f 100644
--- a/src/class_linker_test.cc
+++ b/src/class_linker_test.cc
@@ -947,8 +947,11 @@
   Class* klass = class_linker_->FindClass("LStaticsFromCode;", class_loader.get());
   Method* clinit = klass->FindDirectMethod("<clinit>", "()V");
   Method* getS0 = klass->FindDirectMethod("getS0", "()Ljava/lang/Object;");
-  uint32_t type_idx = FindTypeIdxByDescriptor(*dex_file, "LStaticsFromCode;");
-
+  const DexFile::StringId* string_id = dex_file->FindStringId("LStaticsFromCode;");
+  ASSERT_TRUE(string_id != NULL);
+  const DexFile::TypeId* type_id = dex_file->FindTypeId(dex_file->GetIndexForStringId(*string_id));
+  ASSERT_TRUE(type_id != NULL);
+  uint32_t type_idx = dex_file->GetIndexForTypeId(*type_id);
   EXPECT_TRUE(clinit->GetDexCacheInitializedStaticStorage()->Get(type_idx) == NULL);
   StaticStorageBase* uninit = InitializeStaticStorage(type_idx, clinit, Thread::Current());
   EXPECT_TRUE(uninit != NULL);
diff --git a/src/common_test.h b/src/common_test.h
index c55ef7f..f2a18e5 100644
--- a/src/common_test.h
+++ b/src/common_test.h
@@ -282,31 +282,6 @@
     return DexFile::Open(libcore_dex_file_name, "");
   }
 
-  uint32_t FindTypeIdxByDescriptor(const DexFile& dex_file, const StringPiece& descriptor) {
-    for (size_t i = 0; i < dex_file.NumTypeIds(); i++) {
-      const DexFile::TypeId& type_id = dex_file.GetTypeId(i);
-      if (descriptor == dex_file.GetTypeDescriptor(type_id)) {
-        return i;
-      }
-    }
-    CHECK(false) << "Failed to find type index for " << descriptor;
-    return 0;
-  }
-
-  uint32_t FindFieldIdxByDescriptorAndName(const DexFile& dex_file,
-                                           const StringPiece& class_descriptor,
-                                           const StringPiece& field_name) {
-    for (size_t i = 0; i < dex_file.NumFieldIds(); i++) {
-      const DexFile::FieldId& field_id = dex_file.GetFieldId(i);
-      if (class_descriptor == dex_file.GetFieldDeclaringClassDescriptor(field_id)
-          && field_name == dex_file.GetFieldName(field_id)) {
-        return i;
-      }
-    }
-    CHECK(false) << "Failed to find field index for " << class_descriptor << " " << field_name;
-    return 0;
-  }
-
   const DexFile* OpenTestDexFile(const char* name) {
     CHECK(name != NULL);
     std::string filename;
diff --git a/src/dex_file.cc b/src/dex_file.cc
index e9a883c..208479e 100644
--- a/src/dex_file.cc
+++ b/src/dex_file.cc
@@ -463,11 +463,46 @@
   return NULL;
 }
 
-const DexFile::MethodId* DexFile::FindMethodId(const DexFile::TypeId& klass,
+const DexFile::FieldId* DexFile::FindFieldId(const DexFile::TypeId& declaring_klass,
+                                              const DexFile::StringId& name,
+                                              const DexFile::TypeId& type) const {
+  // Binary search MethodIds knowing that they are sorted by class_idx, name_idx then proto_idx
+  const uint16_t class_idx = GetIndexForTypeId(declaring_klass);
+  const uint32_t name_idx = GetIndexForStringId(name);
+  const uint16_t type_idx = GetIndexForTypeId(type);
+  uint32_t lo = 0;
+  uint32_t hi = NumFieldIds() - 1;
+  while (hi >= lo) {
+    uint32_t mid = (hi + lo) / 2;
+    const DexFile::FieldId& field = GetFieldId(mid);
+    if (class_idx > field.class_idx_) {
+      lo = mid + 1;
+    } else if (class_idx < field.class_idx_) {
+      hi = mid - 1;
+    } else {
+      if (name_idx > field.name_idx_) {
+        lo = mid + 1;
+      } else if (name_idx < field.name_idx_) {
+        hi = mid - 1;
+      } else {
+        if (type_idx > field.type_idx_) {
+          lo = mid + 1;
+        } else if (type_idx < field.type_idx_) {
+          hi = mid - 1;
+        } else {
+          return &field;
+        }
+      }
+    }
+  }
+  return NULL;
+}
+
+const DexFile::MethodId* DexFile::FindMethodId(const DexFile::TypeId& declaring_klass,
                                                const DexFile::StringId& name,
                                                const DexFile::ProtoId& signature) const {
   // Binary search MethodIds knowing that they are sorted by class_idx, name_idx then proto_idx
-  const uint16_t class_idx = GetIndexForTypeId(klass);
+  const uint16_t class_idx = GetIndexForTypeId(declaring_klass);
   const uint32_t name_idx = GetIndexForStringId(name);
   const uint16_t proto_idx = GetIndexForProtoId(signature);
   uint32_t lo = 0;
diff --git a/src/dex_file.h b/src/dex_file.h
index 62b99ab..d48067b 100644
--- a/src/dex_file.h
+++ b/src/dex_file.h
@@ -300,6 +300,17 @@
     return field_ids_[idx];
   }
 
+  uint32_t GetIndexForFieldId(const FieldId& field_id) const {
+    CHECK_GE(&field_id, field_ids_);
+    CHECK_LT(&field_id, field_ids_ + header_->field_ids_size_);
+    return &field_id - field_ids_;
+  }
+
+  // Looks up a field by its declaring class, name and type
+  const FieldId* FindFieldId(const DexFile::TypeId& declaring_klass,
+                             const DexFile::StringId& name,
+                             const DexFile::TypeId& type) const;
+
   // Returns the declaring class descriptor string of a field id.
   const char* GetFieldDeclaringClassDescriptor(const FieldId& field_id) const {
     const DexFile::TypeId& type_id = GetTypeId(field_id.class_idx_);
@@ -335,8 +346,9 @@
     return &method_id - method_ids_;
   }
 
-  // Looks up a method by its class_dex, name and proto_id
-  const MethodId* FindMethodId(const DexFile::TypeId& klass, const DexFile::StringId& name,
+  // Looks up a method by its declaring class, name and proto_id
+  const MethodId* FindMethodId(const DexFile::TypeId& declaring_klass,
+                               const DexFile::StringId& name,
                                const DexFile::ProtoId& signature) const;
 
   // Returns the declaring class descriptor string of a method id.
diff --git a/src/dex_file_test.cc b/src/dex_file_test.cc
index 6f99551..4b311dc 100644
--- a/src/dex_file_test.cc
+++ b/src/dex_file_test.cc
@@ -196,4 +196,19 @@
   }
 }
 
+TEST_F(DexFileTest, FindFieldId) {
+  for (size_t i = 0; i < java_lang_dex_file_->NumFieldIds(); i++) {
+    const DexFile::FieldId& to_find = java_lang_dex_file_->GetFieldId(i);
+    const DexFile::TypeId& klass = java_lang_dex_file_->GetTypeId(to_find.class_idx_);
+    const DexFile::StringId& name = java_lang_dex_file_->GetStringId(to_find.name_idx_);
+    const DexFile::TypeId& type = java_lang_dex_file_->GetTypeId(to_find.type_idx_);
+    const DexFile::FieldId* found = java_lang_dex_file_->FindFieldId(klass, name, type);
+    ASSERT_TRUE(found != NULL) << "Didn't find field " << i << ": "
+        << java_lang_dex_file_->StringByTypeIdx(to_find.type_idx_) << " "
+        << java_lang_dex_file_->StringByTypeIdx(to_find.class_idx_) << "."
+        << java_lang_dex_file_->GetStringData(name);
+    EXPECT_EQ(java_lang_dex_file_->GetIndexForFieldId(*found), i);
+  }
+}
+
 }  // namespace art
diff --git a/src/object_test.cc b/src/object_test.cc
index b09cff1..08abb6f 100644
--- a/src/object_test.cc
+++ b/src/object_test.cc
@@ -169,7 +169,12 @@
   // pretend we are trying to call 'new char[3]' from String.toCharArray
   Class* java_util_Arrays = class_linker_->FindSystemClass("Ljava/util/Arrays;");
   Method* sort = java_util_Arrays->FindDirectMethod("sort", "([I)V");
-  uint32_t type_idx = FindTypeIdxByDescriptor(*java_lang_dex_file_.get(), "[I");
+  const DexFile::StringId* string_id = java_lang_dex_file_->FindStringId("[I");
+  ASSERT_TRUE(string_id != NULL);
+  const DexFile::TypeId* type_id = java_lang_dex_file_->FindTypeId(
+      java_lang_dex_file_->GetIndexForStringId(*string_id));
+  ASSERT_TRUE(type_id != NULL);
+  uint32_t type_idx = java_lang_dex_file_->GetIndexForTypeId(*type_id);
   Object* array = CheckAndAllocArrayFromCode(type_idx, sort, 3, Thread::Current());
   EXPECT_TRUE(array->IsArrayInstance());
   EXPECT_EQ(3, array->AsArray()->GetLength());
@@ -185,7 +190,26 @@
 
   Class* klass = class_linker_->FindClass("LStaticsFromCode;", class_loader.get());
   Method* clinit = klass->FindDirectMethod("<clinit>", "()V");
-  uint32_t field_idx = FindFieldIdxByDescriptorAndName(*dex_file, "LStaticsFromCode;", "s0");
+  const DexFile::StringId* klass_string_id = dex_file->FindStringId("LStaticsFromCode;");
+  ASSERT_TRUE(klass_string_id != NULL);
+  const DexFile::TypeId* klass_type_id = dex_file->FindTypeId(
+      dex_file->GetIndexForStringId(*klass_string_id));
+  ASSERT_TRUE(klass_type_id != NULL);
+
+  const DexFile::StringId* type_string_id = dex_file->FindStringId("Ljava/lang/Object;");
+  ASSERT_TRUE(type_string_id != NULL);
+  const DexFile::TypeId* type_type_id = dex_file->FindTypeId(
+      dex_file->GetIndexForStringId(*type_string_id));
+  ASSERT_TRUE(type_type_id != NULL);
+
+  const DexFile::StringId* name_str_id = dex_file->FindStringId("s0");
+  ASSERT_TRUE(name_str_id != NULL);
+
+  const DexFile::FieldId* field_id = dex_file->FindFieldId(
+      *klass_type_id, *name_str_id, *type_type_id);
+  ASSERT_TRUE(field_id != NULL);
+  uint32_t field_idx = dex_file->GetIndexForFieldId(*field_id);
+
   Field* field = FindFieldFromCode(field_idx, clinit, true);
   Object* s0 = field->GetObj(NULL);
   EXPECT_EQ(NULL, s0);