Clean up AtomicDexRefMap

Make ClassReference, TypeReference, and MethodReference extend
DexFileReference. This enables using all of these types as the key
for AtomicDexRefMap.

Test: test-art-host
Bug: 63851220
Bug: 63756964

Change-Id: Ida3c94cadb53272cb5057e5cebc5971c1ab4d366
diff --git a/compiler/dex/inline_method_analyser.cc b/compiler/dex/inline_method_analyser.cc
index 54ddc21..c8e3d5e 100644
--- a/compiler/dex/inline_method_analyser.cc
+++ b/compiler/dex/inline_method_analyser.cc
@@ -509,7 +509,7 @@
 }
 
 bool InlineMethodAnalyser::IsSyntheticAccessor(MethodReference ref) {
-  const DexFile::MethodId& method_id = ref.dex_file->GetMethodId(ref.dex_method_index);
+  const DexFile::MethodId& method_id = ref.dex_file->GetMethodId(ref.index);
   const char* method_name = ref.dex_file->GetMethodName(method_id);
   // javac names synthetic accessors "access$nnn",
   // jack names them "-getN", "-putN", "-wrapN".
diff --git a/compiler/dex/verification_results.cc b/compiler/dex/verification_results.cc
index cfb56e3..03c90d8 100644
--- a/compiler/dex/verification_results.cc
+++ b/compiler/dex/verification_results.cc
@@ -52,18 +52,16 @@
     // We'll punt this later.
     return;
   }
-  AtomicMap::InsertResult result = atomic_verified_methods_.Insert(
-      DexFileReference(ref.dex_file, ref.dex_method_index),
-      /*expected*/ nullptr,
-      verified_method.get());
+  AtomicMap::InsertResult result = atomic_verified_methods_.Insert(ref,
+                                                                   /*expected*/ nullptr,
+                                                                   verified_method.get());
   const VerifiedMethod* existing = nullptr;
   bool inserted;
   if (result != AtomicMap::kInsertResultInvalidDexFile) {
     inserted = (result == AtomicMap::kInsertResultSuccess);
     if (!inserted) {
       // Rare case.
-      CHECK(atomic_verified_methods_.Get(DexFileReference(ref.dex_file, ref.dex_method_index),
-                                         &existing));
+      CHECK(atomic_verified_methods_.Get(ref, &existing));
       CHECK_NE(verified_method.get(), existing);
     }
   } else {
@@ -100,7 +98,7 @@
 
 const VerifiedMethod* VerificationResults::GetVerifiedMethod(MethodReference ref) {
   const VerifiedMethod* ret = nullptr;
-  if (atomic_verified_methods_.Get(DexFileReference(ref.dex_file, ref.dex_method_index), &ret)) {
+  if (atomic_verified_methods_.Get(ref, &ret)) {
     return ret;
   }
   ReaderMutexLock mu(Thread::Current(), verified_methods_lock_);
@@ -114,7 +112,7 @@
   // at runtime.
   std::unique_ptr<VerifiedMethod> verified_method = std::make_unique<VerifiedMethod>(
       /* encountered_error_types */ 0, /* has_runtime_throw */ false);
-  if (atomic_verified_methods_.Insert(DexFileReference(ref.dex_file, ref.dex_method_index),
+  if (atomic_verified_methods_.Insert(ref,
                                       /*expected*/ nullptr,
                                       verified_method.get()) ==
           AtomicMap::InsertResult::kInsertResultSuccess) {
@@ -149,7 +147,7 @@
 }
 
 void VerificationResults::AddDexFile(const DexFile* dex_file) {
-  atomic_verified_methods_.AddDexFile(dex_file, dex_file->NumMethodIds());
+  atomic_verified_methods_.AddDexFile(dex_file);
   WriterMutexLock mu(Thread::Current(), verified_methods_lock_);
   // There can be some verified methods that are already registered for the dex_file since we set
   // up well known classes earlier. Remove these and put them in the array so that we don't
@@ -157,9 +155,7 @@
   for (auto it = verified_methods_.begin(); it != verified_methods_.end(); ) {
     MethodReference ref = it->first;
     if (ref.dex_file == dex_file) {
-      CHECK(atomic_verified_methods_.Insert(DexFileReference(ref.dex_file, ref.dex_method_index),
-                                            nullptr,
-                                            it->second) ==
+      CHECK(atomic_verified_methods_.Insert(ref, nullptr, it->second) ==
           AtomicMap::kInsertResultSuccess);
       it = verified_methods_.erase(it);
     } else {
diff --git a/compiler/dex/verification_results.h b/compiler/dex/verification_results.h
index 5a03599..d19e993 100644
--- a/compiler/dex/verification_results.h
+++ b/compiler/dex/verification_results.h
@@ -64,10 +64,8 @@
 
  private:
   // Verified methods. The method array is fixed to avoid needing a lock to extend it.
-  using AtomicMap = AtomicDexRefMap<const VerifiedMethod*>;
-  using VerifiedMethodMap = SafeMap<MethodReference,
-                                    const VerifiedMethod*,
-                                    MethodReferenceComparator>;
+  using AtomicMap = AtomicDexRefMap<MethodReference, const VerifiedMethod*>;
+  using VerifiedMethodMap = SafeMap<MethodReference, const VerifiedMethod*>;
 
   VerifiedMethodMap verified_methods_ GUARDED_BY(verified_methods_lock_);
   const CompilerOptions* const compiler_options_;
diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc
index b9c0314..678f090 100644
--- a/compiler/driver/compiler_driver.cc
+++ b/compiler/driver/compiler_driver.cc
@@ -896,7 +896,7 @@
     for (const DexFile* dex_file : dex_files) {
       // Can be already inserted if the caller is CompileOne. This happens for gtests.
       if (!compiled_methods_.HaveDexFile(dex_file)) {
-        compiled_methods_.AddDexFile(dex_file, dex_file->NumMethodIds());
+        compiled_methods_.AddDexFile(dex_file);
       }
     }
     // Resolve eagerly to prepare for compilation.
@@ -964,7 +964,7 @@
     return true;
   }
 
-  std::string tmp = method_ref.dex_file->PrettyMethod(method_ref.dex_method_index, true);
+  std::string tmp = method_ref.PrettyMethod();
   return methods_to_compile_->find(tmp.c_str()) != methods_to_compile_->end();
 }
 
@@ -985,8 +985,7 @@
 
   if (kDebugProfileGuidedCompilation) {
     LOG(INFO) << "[ProfileGuidedCompilation] "
-        << (result ? "Compiled" : "Skipped") << " method:"
-        << method_ref.dex_file->PrettyMethod(method_ref.dex_method_index, true);
+        << (result ? "Compiled" : "Skipped") << " method:" << method_ref.PrettyMethod(true);
   }
   return result;
 }
@@ -1359,7 +1358,7 @@
       &dex_to_dex_references_.back().GetDexFile() != method_ref.dex_file) {
     dex_to_dex_references_.emplace_back(*method_ref.dex_file);
   }
-  dex_to_dex_references_.back().GetMethodIndexes().SetBit(method_ref.dex_method_index);
+  dex_to_dex_references_.back().GetMethodIndexes().SetBit(method_ref.index);
 }
 
 bool CompilerDriver::CanAccessTypeWithoutChecks(ObjPtr<mirror::Class> referrer_class,
@@ -1944,7 +1943,7 @@
         if (compiler_only_verifies) {
           // Just update the compiled_classes_ map. The compiler doesn't need to resolve
           // the type.
-          DexFileReference ref(dex_file, i);
+          ClassReference ref(dex_file, i);
           mirror::Class::Status existing = mirror::Class::kStatusNotReady;
           DCHECK(compiled_classes_.Get(ref, &existing)) << ref.dex_file->GetLocation();
           ClassStateTable::InsertResult result =
@@ -2220,7 +2219,7 @@
                                         TimingLogger* timings) {
   TimingLogger::ScopedTiming t("Verify Dex File", timings);
   if (!compiled_classes_.HaveDexFile(&dex_file)) {
-    compiled_classes_.AddDexFile(&dex_file, dex_file.NumClassDefs());
+    compiled_classes_.AddDexFile(&dex_file);
   }
   ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
   ParallelCompilationManager context(class_linker, class_loader, this, &dex_file, dex_files,
@@ -2877,38 +2876,36 @@
 void CompilerDriver::AddCompiledMethod(const MethodReference& method_ref,
                                        CompiledMethod* const compiled_method,
                                        size_t non_relative_linker_patch_count) {
-  DCHECK(GetCompiledMethod(method_ref) == nullptr)
-      << method_ref.dex_file->PrettyMethod(method_ref.dex_method_index);
-  MethodTable::InsertResult result = compiled_methods_.Insert(
-      DexFileReference(method_ref.dex_file, method_ref.dex_method_index),
-      /*expected*/ nullptr,
-      compiled_method);
+  DCHECK(GetCompiledMethod(method_ref) == nullptr) << method_ref.PrettyMethod();
+  MethodTable::InsertResult result = compiled_methods_.Insert(method_ref,
+                                                              /*expected*/ nullptr,
+                                                              compiled_method);
   CHECK(result == MethodTable::kInsertResultSuccess);
   non_relative_linker_patch_count_.FetchAndAddRelaxed(non_relative_linker_patch_count);
-  DCHECK(GetCompiledMethod(method_ref) != nullptr)
-      << method_ref.dex_file->PrettyMethod(method_ref.dex_method_index);
+  DCHECK(GetCompiledMethod(method_ref) != nullptr) << method_ref.PrettyMethod();
 }
 
-bool CompilerDriver::GetCompiledClass(ClassReference ref, mirror::Class::Status* status) const {
+bool CompilerDriver::GetCompiledClass(const ClassReference& ref,
+                                      mirror::Class::Status* status) const {
   DCHECK(status != nullptr);
   // The table doesn't know if something wasn't inserted. For this case it will return
   // kStatusNotReady. To handle this, just assume anything we didn't try to verify is not compiled.
-  if (!compiled_classes_.Get(DexFileReference(ref.first, ref.second), status) ||
+  if (!compiled_classes_.Get(ref, status) ||
       *status < mirror::Class::kStatusRetryVerificationAtRuntime) {
     return false;
   }
   return true;
 }
 
-mirror::Class::Status CompilerDriver::GetClassStatus(ClassReference ref) const {
+mirror::Class::Status CompilerDriver::GetClassStatus(const ClassReference& ref) const {
   mirror::Class::Status status = ClassStatus::kStatusNotReady;
   if (!GetCompiledClass(ref, &status)) {
-    classpath_classes_.Get(DexFileReference(ref.first, ref.second), &status);
+    classpath_classes_.Get(ref, &status);
   }
   return status;
 }
 
-void CompilerDriver::RecordClassStatus(ClassReference ref, mirror::Class::Status status) {
+void CompilerDriver::RecordClassStatus(const ClassReference& ref, mirror::Class::Status status) {
   switch (status) {
     case mirror::Class::kStatusErrorResolved:
     case mirror::Class::kStatusErrorUnresolved:
@@ -2921,30 +2918,30 @@
       break;  // Expected states.
     default:
       LOG(FATAL) << "Unexpected class status for class "
-          << PrettyDescriptor(ref.first->GetClassDescriptor(ref.first->GetClassDef(ref.second)))
+          << PrettyDescriptor(
+              ref.dex_file->GetClassDescriptor(ref.dex_file->GetClassDef(ref.index)))
           << " of " << status;
   }
 
   ClassStateTable::InsertResult result;
   ClassStateTable* table = &compiled_classes_;
   do {
-    DexFileReference dex_ref(ref.first, ref.second);
     mirror::Class::Status existing = mirror::Class::kStatusNotReady;
-    if (!table->Get(dex_ref, &existing)) {
+    if (!table->Get(ref, &existing)) {
       // A classpath class.
       if (kIsDebugBuild) {
         // Check to make sure it's not a dex file for an oat file we are compiling since these
         // should always succeed. These do not include classes in for used libraries.
         for (const DexFile* dex_file : GetDexFilesForOatFile()) {
-          CHECK_NE(dex_ref.dex_file, dex_file) << dex_ref.dex_file->GetLocation();
+          CHECK_NE(ref.dex_file, dex_file) << ref.dex_file->GetLocation();
         }
       }
-      if (!classpath_classes_.HaveDexFile(ref.first)) {
+      if (!classpath_classes_.HaveDexFile(ref.dex_file)) {
         // Boot classpath dex file.
         return;
       }
       table = &classpath_classes_;
-      table->Get(dex_ref, &existing);
+      table->Get(ref, &existing);
     }
     if (existing >= status) {
       // Existing status is already better than we expect, break.
@@ -2952,14 +2949,14 @@
     }
     // Update the status if we now have a greater one. This happens with vdex,
     // which records a class is verified, but does not resolve it.
-    result = table->Insert(dex_ref, existing, status);
-    CHECK(result != ClassStateTable::kInsertResultInvalidDexFile) << ref.first->GetLocation();
+    result = table->Insert(ref, existing, status);
+    CHECK(result != ClassStateTable::kInsertResultInvalidDexFile) << ref.dex_file->GetLocation();
   } while (result != ClassStateTable::kInsertResultSuccess);
 }
 
 CompiledMethod* CompilerDriver::GetCompiledMethod(MethodReference ref) const {
   CompiledMethod* compiled_method = nullptr;
-  compiled_methods_.Get(DexFileReference(ref.dex_file, ref.dex_method_index), &compiled_method);
+  compiled_methods_.Get(ref, &compiled_method);
   return compiled_method;
 }
 
diff --git a/compiler/driver/compiler_driver.h b/compiler/driver/compiler_driver.h
index 5043884..0d1cce7 100644
--- a/compiler/driver/compiler_driver.h
+++ b/compiler/driver/compiler_driver.h
@@ -154,8 +154,8 @@
   std::unique_ptr<const std::vector<uint8_t>> CreateQuickResolutionTrampoline() const;
   std::unique_ptr<const std::vector<uint8_t>> CreateQuickToInterpreterBridge() const;
 
-  bool GetCompiledClass(ClassReference ref, mirror::Class::Status* status) const;
-  mirror::Class::Status GetClassStatus(ClassReference ref) const;
+  mirror::Class::Status GetClassStatus(const ClassReference& ref) const;
+  bool GetCompiledClass(const ClassReference& ref, mirror::Class::Status* status) const;
 
   CompiledMethod* GetCompiledMethod(MethodReference ref) const;
   size_t GetNonRelativeLinkerPatchCount() const;
@@ -338,7 +338,7 @@
   // according to the profile file.
   bool ShouldVerifyClassBasedOnProfile(const DexFile& dex_file, uint16_t class_idx) const;
 
-  void RecordClassStatus(ClassReference ref, mirror::Class::Status status);
+  void RecordClassStatus(const ClassReference& ref, mirror::Class::Status status);
 
   // Checks if the specified method has been verified without failures. Returns
   // false if the method is not in the verification results (GetVerificationResults).
@@ -489,13 +489,13 @@
   std::map<ClassReference, bool> requires_constructor_barrier_
       GUARDED_BY(requires_constructor_barrier_lock_);
 
-  using ClassStateTable = AtomicDexRefMap<mirror::Class::Status>;
   // All class references that this compiler has compiled. Indexed by class defs.
+  using ClassStateTable = AtomicDexRefMap<ClassReference, mirror::Class::Status>;
   ClassStateTable compiled_classes_;
   // All class references that are in the classpath. Indexed by class defs.
   ClassStateTable classpath_classes_;
 
-  typedef AtomicDexRefMap<CompiledMethod*> MethodTable;
+  typedef AtomicDexRefMap<MethodReference, CompiledMethod*> MethodTable;
 
  private:
   // All method references that this compiler has compiled.
diff --git a/compiler/linker/arm/relative_patcher_arm_base.cc b/compiler/linker/arm/relative_patcher_arm_base.cc
index 6e63bf8..1b061b3 100644
--- a/compiler/linker/arm/relative_patcher_arm_base.cc
+++ b/compiler/linker/arm/relative_patcher_arm_base.cc
@@ -469,8 +469,7 @@
     if (!method_call_thunk_->HasReservedOffset() ||
         patch_offset - method_call_thunk_->LastReservedOffset() > max_negative_displacement) {
       // No previous thunk in range, check if we can reach the target directly.
-      if (target_method.dex_file == method_ref.dex_file &&
-          target_method.dex_method_index == method_ref.dex_method_index) {
+      if (target_method == method_ref) {
         DCHECK_GT(quick_code_offset, patch_offset);
         if (quick_code_offset - patch_offset > max_positive_displacement) {
           break;
diff --git a/compiler/linker/arm64/relative_patcher_arm64_test.cc b/compiler/linker/arm64/relative_patcher_arm64_test.cc
index d6919e9..8a5b4cc 100644
--- a/compiler/linker/arm64/relative_patcher_arm64_test.cc
+++ b/compiler/linker/arm64/relative_patcher_arm64_test.cc
@@ -344,7 +344,7 @@
                                        uint32_t use_insn) {
     uint32_t method1_offset = GetMethodOffset(1u);
     CHECK(!compiled_method_refs_.empty());
-    CHECK_EQ(compiled_method_refs_[0].dex_method_index, 1u);
+    CHECK_EQ(compiled_method_refs_[0].index, 1u);
     CHECK_EQ(compiled_method_refs_.size(), compiled_methods_.size());
     uint32_t method1_size = compiled_methods_[0]->GetQuickCode().size();
     uint32_t thunk_offset = CompiledCode::AlignCode(method1_offset + method1_size, kArm64);
diff --git a/compiler/linker/multi_oat_relative_patcher.h b/compiler/linker/multi_oat_relative_patcher.h
index 1c5c8a0..02cd4b0 100644
--- a/compiler/linker/multi_oat_relative_patcher.h
+++ b/compiler/linker/multi_oat_relative_patcher.h
@@ -37,8 +37,7 @@
 // to the value set by SetAdjustment().
 class MultiOatRelativePatcher FINAL {
  public:
-  using const_iterator =
-      SafeMap<MethodReference, uint32_t, MethodReferenceComparator>::const_iterator;
+  using const_iterator = SafeMap<MethodReference, uint32_t>::const_iterator;
 
   MultiOatRelativePatcher(InstructionSet instruction_set, const InstructionSetFeatures* features);
 
@@ -136,7 +135,7 @@
   class MethodOffsetMap : public linker::RelativePatcherTargetProvider {
    public:
     std::pair<bool, uint32_t> FindMethodOffset(MethodReference ref) OVERRIDE;
-    SafeMap<MethodReference, uint32_t, MethodReferenceComparator> map;
+    SafeMap<MethodReference, uint32_t> map;
   };
 
   MethodOffsetMap method_offset_map_;
diff --git a/compiler/linker/multi_oat_relative_patcher_test.cc b/compiler/linker/multi_oat_relative_patcher_test.cc
index f89fba6..5c359dc 100644
--- a/compiler/linker/multi_oat_relative_patcher_test.cc
+++ b/compiler/linker/multi_oat_relative_patcher_test.cc
@@ -26,10 +26,6 @@
 
 static const MethodReference kNullMethodRef = MethodReference(nullptr, 0u);
 
-static bool EqualRef(MethodReference lhs, MethodReference rhs) {
-  return lhs.dex_file == rhs.dex_file && lhs.dex_method_index == rhs.dex_method_index;
-}
-
 class MultiOatRelativePatcherTest : public testing::Test {
  protected:
   class MockPatcher : public RelativePatcher {
@@ -182,7 +178,7 @@
   uint32_t method1_offset = 0x100;
   uint32_t method1_offset_check = patcher_.ReserveSpace(method1_offset, method, ref1);
   ASSERT_EQ(adjustment1 + method1_offset, mock_->last_reserve_offset_);
-  ASSERT_TRUE(EqualRef(ref1, mock_->last_reserve_method_));
+  ASSERT_TRUE(ref1 == mock_->last_reserve_method_);
   ASSERT_EQ(method1_offset, method1_offset_check);
 
   uint32_t method2_offset = 0x1230;
@@ -190,13 +186,13 @@
   mock_->next_reserve_adjustment_ = method2_reserve_adjustment;
   uint32_t method2_offset_adjusted = patcher_.ReserveSpace(method2_offset, method, ref2);
   ASSERT_EQ(adjustment1 + method2_offset, mock_->last_reserve_offset_);
-  ASSERT_TRUE(EqualRef(ref2, mock_->last_reserve_method_));
+  ASSERT_TRUE(ref2 == mock_->last_reserve_method_);
   ASSERT_EQ(method2_offset + method2_reserve_adjustment, method2_offset_adjusted);
 
   uint32_t end1_offset = 0x4320;
   uint32_t end1_offset_check = patcher_.ReserveSpaceEnd(end1_offset);
   ASSERT_EQ(adjustment1 + end1_offset, mock_->last_reserve_offset_);
-  ASSERT_TRUE(EqualRef(kNullMethodRef, mock_->last_reserve_method_));
+  ASSERT_TRUE(kNullMethodRef == mock_->last_reserve_method_);
   ASSERT_EQ(end1_offset, end1_offset_check);
 
   uint32_t adjustment2 = 0xd000;
@@ -205,7 +201,7 @@
   uint32_t method3_offset = 0xf00;
   uint32_t method3_offset_check = patcher_.ReserveSpace(method3_offset, method, ref3);
   ASSERT_EQ(adjustment2 + method3_offset, mock_->last_reserve_offset_);
-  ASSERT_TRUE(EqualRef(ref3, mock_->last_reserve_method_));
+  ASSERT_TRUE(ref3 == mock_->last_reserve_method_);
   ASSERT_EQ(method3_offset, method3_offset_check);
 
   uint32_t end2_offset = 0x2400;
@@ -213,7 +209,7 @@
   mock_->next_reserve_adjustment_ = end2_reserve_adjustment;
   uint32_t end2_offset_adjusted = patcher_.ReserveSpaceEnd(end2_offset);
   ASSERT_EQ(adjustment2 + end2_offset, mock_->last_reserve_offset_);
-  ASSERT_TRUE(EqualRef(kNullMethodRef, mock_->last_reserve_method_));
+  ASSERT_TRUE(kNullMethodRef == mock_->last_reserve_method_);
   ASSERT_EQ(end2_offset + end2_reserve_adjustment, end2_offset_adjusted);
 }
 
diff --git a/compiler/linker/relative_patcher_test.h b/compiler/linker/relative_patcher_test.h
index bff6808..ca8743a 100644
--- a/compiler/linker/relative_patcher_test.h
+++ b/compiler/linker/relative_patcher_test.h
@@ -194,8 +194,7 @@
     // Sanity check: original code size must match linked_code.size().
     size_t idx = 0u;
     for (auto ref : compiled_method_refs_) {
-      if (ref.dex_file == method_ref.dex_file &&
-          ref.dex_method_index == method_ref.dex_method_index) {
+      if (ref == method_ref) {
         break;
       }
       ++idx;
@@ -264,7 +263,7 @@
         return std::pair<bool, uint32_t>(true, it->second);
       }
     }
-    SafeMap<MethodReference, uint32_t, MethodReferenceComparator> map;
+    SafeMap<MethodReference, uint32_t> map;
   };
 
   static const uint32_t kTrampolineSize = 4u;
diff --git a/compiler/oat_writer.cc b/compiler/oat_writer.cc
index 7ae3866..0bd3587 100644
--- a/compiler/oat_writer.cc
+++ b/compiler/oat_writer.cc
@@ -765,7 +765,7 @@
                           Allocator::GetMallocAllocator()));
             refs_it->second.ClearAllBits();
           }
-          refs_it->second.SetBit(target_method.dex_method_index);
+          refs_it->second.SetBit(target_method.index);
           writer_->bss_method_entries_.Overwrite(target_method, /* placeholder */ 0u);
         } else if (patch.GetType() == LinkerPatch::Type::kTypeBssEntry) {
           TypeReference ref(patch.TargetTypeDexFile(), patch.TargetTypeIndex());
@@ -922,7 +922,7 @@
         if (relative_patcher_->GetOffset(method_ref) != 0u) {
           // TODO: Should this be a hard failure?
           LOG(WARNING) << "Multiple definitions of "
-              << method_ref.dex_file->PrettyMethod(method_ref.dex_method_index)
+              << method_ref.PrettyMethod()
               << " offsets " << relative_patcher_->GetOffset(method_ref)
               << " " << quick_code_offset;
         } else {
@@ -1526,8 +1526,7 @@
     ObjPtr<mirror::DexCache> dex_cache =
         (dex_file_ == ref.dex_file) ? dex_cache_ : class_linker_->FindDexCache(
             Thread::Current(), *ref.dex_file);
-    ArtMethod* method =
-        class_linker_->LookupResolvedMethod(ref.dex_method_index, dex_cache, class_loader_);
+    ArtMethod* method = class_linker_->LookupResolvedMethod(ref.index, dex_cache, class_loader_);
     CHECK(method != nullptr);
     return method;
   }
diff --git a/compiler/optimizing/code_generator_arm64.cc b/compiler/optimizing/code_generator_arm64.cc
index 19e5d06..c61ef0a 100644
--- a/compiler/optimizing/code_generator_arm64.cc
+++ b/compiler/optimizing/code_generator_arm64.cc
@@ -4641,7 +4641,7 @@
     MethodReference target_method,
     vixl::aarch64::Label* adrp_label) {
   return NewPcRelativePatch(*target_method.dex_file,
-                            target_method.dex_method_index,
+                            target_method.index,
                             adrp_label,
                             &pc_relative_method_patches_);
 }
@@ -4650,7 +4650,7 @@
     MethodReference target_method,
     vixl::aarch64::Label* adrp_label) {
   return NewPcRelativePatch(*target_method.dex_file,
-                            target_method.dex_method_index,
+                            target_method.index,
                             adrp_label,
                             &method_bss_entry_patches_);
 }
diff --git a/compiler/optimizing/code_generator_arm_vixl.cc b/compiler/optimizing/code_generator_arm_vixl.cc
index 8b9495d..6147259 100644
--- a/compiler/optimizing/code_generator_arm_vixl.cc
+++ b/compiler/optimizing/code_generator_arm_vixl.cc
@@ -9119,14 +9119,14 @@
 CodeGeneratorARMVIXL::PcRelativePatchInfo* CodeGeneratorARMVIXL::NewPcRelativeMethodPatch(
     MethodReference target_method) {
   return NewPcRelativePatch(*target_method.dex_file,
-                            target_method.dex_method_index,
+                            target_method.index,
                             &pc_relative_method_patches_);
 }
 
 CodeGeneratorARMVIXL::PcRelativePatchInfo* CodeGeneratorARMVIXL::NewMethodBssEntryPatch(
     MethodReference target_method) {
   return NewPcRelativePatch(*target_method.dex_file,
-                            target_method.dex_method_index,
+                            target_method.index,
                             &method_bss_entry_patches_);
 }
 
diff --git a/compiler/optimizing/code_generator_mips.cc b/compiler/optimizing/code_generator_mips.cc
index f0ef007..9db2bd3 100644
--- a/compiler/optimizing/code_generator_mips.cc
+++ b/compiler/optimizing/code_generator_mips.cc
@@ -1683,7 +1683,7 @@
     MethodReference target_method,
     const PcRelativePatchInfo* info_high) {
   return NewPcRelativePatch(*target_method.dex_file,
-                            target_method.dex_method_index,
+                            target_method.index,
                             info_high,
                             &pc_relative_method_patches_);
 }
@@ -1692,7 +1692,7 @@
     MethodReference target_method,
     const PcRelativePatchInfo* info_high) {
   return NewPcRelativePatch(*target_method.dex_file,
-                            target_method.dex_method_index,
+                            target_method.index,
                             info_high,
                             &method_bss_entry_patches_);
 }
diff --git a/compiler/optimizing/code_generator_mips64.cc b/compiler/optimizing/code_generator_mips64.cc
index 201b1b0..a27cbce 100644
--- a/compiler/optimizing/code_generator_mips64.cc
+++ b/compiler/optimizing/code_generator_mips64.cc
@@ -1592,7 +1592,7 @@
     MethodReference target_method,
     const PcRelativePatchInfo* info_high) {
   return NewPcRelativePatch(*target_method.dex_file,
-                            target_method.dex_method_index,
+                            target_method.index,
                             info_high,
                             &pc_relative_method_patches_);
 }
@@ -1601,7 +1601,7 @@
     MethodReference target_method,
     const PcRelativePatchInfo* info_high) {
   return NewPcRelativePatch(*target_method.dex_file,
-                            target_method.dex_method_index,
+                            target_method.index,
                             info_high,
                             &method_bss_entry_patches_);
 }
diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc
index e45ad0a..c153cf7 100644
--- a/compiler/optimizing/code_generator_x86.cc
+++ b/compiler/optimizing/code_generator_x86.cc
@@ -4623,7 +4623,7 @@
       invoke->InputAt(invoke->GetSpecialInputIndex())->AsX86ComputeBaseMethodAddress();
   boot_image_method_patches_.emplace_back(address,
                                           *invoke->GetTargetMethod().dex_file,
-                                          invoke->GetTargetMethod().dex_method_index);
+                                          invoke->GetTargetMethod().index);
   __ Bind(&boot_image_method_patches_.back().label);
 }
 
@@ -4633,7 +4633,7 @@
   // Add the patch entry and bind its label at the end of the instruction.
   method_bss_entry_patches_.emplace_back(method_address,
                                          *target_method.dex_file,
-                                         target_method.dex_method_index);
+                                         target_method.index);
   return &method_bss_entry_patches_.back().label;
 }
 
diff --git a/compiler/optimizing/code_generator_x86_64.cc b/compiler/optimizing/code_generator_x86_64.cc
index 8c4374d..bbf05a7 100644
--- a/compiler/optimizing/code_generator_x86_64.cc
+++ b/compiler/optimizing/code_generator_x86_64.cc
@@ -1068,13 +1068,13 @@
 
 void CodeGeneratorX86_64::RecordBootMethodPatch(HInvokeStaticOrDirect* invoke) {
   boot_image_method_patches_.emplace_back(*invoke->GetTargetMethod().dex_file,
-                                          invoke->GetTargetMethod().dex_method_index);
+                                          invoke->GetTargetMethod().index);
   __ Bind(&boot_image_method_patches_.back().label);
 }
 
 Label* CodeGeneratorX86_64::NewMethodBssEntryPatch(MethodReference target_method) {
   // Add a patch entry and return the label.
-  method_bss_entry_patches_.emplace_back(*target_method.dex_file, target_method.dex_method_index);
+  method_bss_entry_patches_.emplace_back(*target_method.dex_file, target_method.index);
   return &method_bss_entry_patches_.back().label;
 }
 
diff --git a/compiler/utils/atomic_dex_ref_map-inl.h b/compiler/utils/atomic_dex_ref_map-inl.h
index 14f1f0b..33d59f9 100644
--- a/compiler/utils/atomic_dex_ref_map-inl.h
+++ b/compiler/utils/atomic_dex_ref_map-inl.h
@@ -19,15 +19,40 @@
 
 #include "atomic_dex_ref_map.h"
 
+#include <type_traits>
+
 #include "dex_file-inl.h"
+#include "class_reference.h"
+#include "method_reference.h"
+#include "type_reference.h"
 
 namespace art {
 
-template <typename T>
-inline typename AtomicDexRefMap<T>::InsertResult AtomicDexRefMap<T>::Insert(
-    DexFileReference ref,
-    const T& expected,
-    const T& desired) {
+template <typename DexFileReferenceType, typename Value>
+inline size_t AtomicDexRefMap<DexFileReferenceType, Value>::NumberOfDexIndices(
+    const DexFile* dex_file) {
+  // TODO: Use specialization for this? Not sure if worth it.
+  static_assert(std::is_same<DexFileReferenceType, MethodReference>::value ||
+                std::is_same<DexFileReferenceType, ClassReference>::value ||
+                std::is_same<DexFileReferenceType, TypeReference>::value,
+                "invalid index type");
+  if (std::is_same<DexFileReferenceType, MethodReference>::value) {
+    return dex_file->NumMethodIds();
+  }
+  if (std::is_same<DexFileReferenceType, ClassReference>::value) {
+    return dex_file->NumClassDefs();
+  }
+  if (std::is_same<DexFileReferenceType, TypeReference>::value) {
+    return dex_file->NumTypeIds();
+  }
+  UNREACHABLE();
+}
+
+template <typename DexFileReferenceType, typename Value>
+inline typename AtomicDexRefMap<DexFileReferenceType, Value>::InsertResult
+    AtomicDexRefMap<DexFileReferenceType, Value>::Insert(const DexFileReferenceType& ref,
+                                                         const Value& expected,
+                                                         const Value& desired) {
   ElementArray* const array = GetArray(ref.dex_file);
   if (array == nullptr) {
     return kInsertResultInvalidDexFile;
@@ -38,8 +63,9 @@
       : kInsertResultCASFailure;
 }
 
-template <typename T>
-inline bool AtomicDexRefMap<T>::Get(DexFileReference ref, T* out) const {
+template <typename DexFileReferenceType, typename Value>
+inline bool AtomicDexRefMap<DexFileReferenceType, Value>::Get(const DexFileReferenceType& ref,
+                                                              Value* out) const {
   const ElementArray* const array = GetArray(ref.dex_file);
   if (array == nullptr) {
     return false;
@@ -48,36 +74,37 @@
   return true;
 }
 
-template <typename T>
-inline void AtomicDexRefMap<T>::AddDexFile(const DexFile* dex_file, size_t max_index) {
-  arrays_.Put(dex_file, std::move(ElementArray(max_index)));
+template <typename DexFileReferenceType, typename Value>
+inline void AtomicDexRefMap<DexFileReferenceType, Value>::AddDexFile(const DexFile* dex_file) {
+  arrays_.Put(dex_file, std::move(ElementArray(NumberOfDexIndices(dex_file))));
 }
 
-template <typename T>
-inline void AtomicDexRefMap<T>::AddDexFiles(const std::vector<const DexFile*>& dex_files) {
+template <typename DexFileReferenceType, typename Value>
+inline void AtomicDexRefMap<DexFileReferenceType, Value>::AddDexFiles(
+    const std::vector<const DexFile*>& dex_files) {
   for (const DexFile* dex_file : dex_files) {
     if (!HaveDexFile(dex_file)) {
-      AddDexFile(dex_file, dex_file->NumClassDefs());
+      AddDexFile(dex_file);
     }
   }
 }
 
-template <typename T>
-inline typename AtomicDexRefMap<T>::ElementArray* AtomicDexRefMap<T>::GetArray(
-    const DexFile* dex_file) {
+template <typename DexFileReferenceType, typename Value>
+inline typename AtomicDexRefMap<DexFileReferenceType, Value>::ElementArray*
+    AtomicDexRefMap<DexFileReferenceType, Value>::GetArray(const DexFile* dex_file) {
   auto it = arrays_.find(dex_file);
   return (it != arrays_.end()) ? &it->second : nullptr;
 }
 
-template <typename T>
-inline const typename AtomicDexRefMap<T>::ElementArray* AtomicDexRefMap<T>::GetArray(
-    const DexFile* dex_file) const {
+template <typename DexFileReferenceType, typename Value>
+inline const typename AtomicDexRefMap<DexFileReferenceType, Value>::ElementArray*
+    AtomicDexRefMap<DexFileReferenceType, Value>::GetArray(const DexFile* dex_file) const {
   auto it = arrays_.find(dex_file);
   return (it != arrays_.end()) ? &it->second : nullptr;
 }
 
-template <typename T> template <typename Visitor>
-inline void AtomicDexRefMap<T>::Visit(const Visitor& visitor) {
+template <typename DexFileReferenceType, typename Value> template <typename Visitor>
+inline void AtomicDexRefMap<DexFileReferenceType, Value>::Visit(const Visitor& visitor) {
   for (auto& pair : arrays_) {
     const DexFile* dex_file = pair.first;
     const ElementArray& elements = pair.second;
@@ -87,8 +114,8 @@
   }
 }
 
-template <typename T>
-inline void AtomicDexRefMap<T>::ClearEntries() {
+template <typename DexFileReferenceType, typename Value>
+inline void AtomicDexRefMap<DexFileReferenceType, Value>::ClearEntries() {
   for (auto& it : arrays_) {
     for (auto& element : it.second) {
       element.StoreRelaxed(nullptr);
diff --git a/compiler/utils/atomic_dex_ref_map.h b/compiler/utils/atomic_dex_ref_map.h
index b02c9b6..fad056c 100644
--- a/compiler/utils/atomic_dex_ref_map.h
+++ b/compiler/utils/atomic_dex_ref_map.h
@@ -18,7 +18,7 @@
 #define ART_COMPILER_UTILS_ATOMIC_DEX_REF_MAP_H_
 
 #include "base/dchecked_vector.h"
-#include "dex_file.h"
+#include "dex_file_reference.h"
 #include "safe_map.h"
 
 namespace art {
@@ -26,7 +26,7 @@
 class DexFile;
 
 // Used by CompilerCallbacks to track verification information from the Runtime.
-template <typename T>
+template <typename DexFileReferenceType, typename Value>
 class AtomicDexRefMap {
  public:
   explicit AtomicDexRefMap() {}
@@ -38,14 +38,16 @@
     kInsertResultCASFailure,
     kInsertResultSuccess,
   };
-  InsertResult Insert(DexFileReference ref, const T& expected, const T& desired);
+  InsertResult Insert(const DexFileReferenceType& ref,
+                      const Value& expected,
+                      const Value& desired);
 
   // Retreive an item, returns false if the dex file is not added.
-  bool Get(DexFileReference ref, T* out) const;
+  bool Get(const DexFileReferenceType& ref, Value* out) const;
 
   // Dex files must be added before method references belonging to them can be used as keys. Not
   // thread safe.
-  void AddDexFile(const DexFile* dex_file, size_t max_index);
+  void AddDexFile(const DexFile* dex_file);
   void AddDexFiles(const std::vector<const DexFile*>& dex_files);
 
   bool HaveDexFile(const DexFile* dex_file) const {
@@ -60,12 +62,14 @@
 
  private:
   // Verified methods. The method array is fixed to avoid needing a lock to extend it.
-  using ElementArray = dchecked_vector<Atomic<T>>;
+  using ElementArray = dchecked_vector<Atomic<Value>>;
   using DexFileArrays = SafeMap<const DexFile*, ElementArray>;
 
   const ElementArray* GetArray(const DexFile* dex_file) const;
   ElementArray* GetArray(const DexFile* dex_file);
 
+  static size_t NumberOfDexIndices(const DexFile* dex_file);
+
   DexFileArrays arrays_;
 };
 
diff --git a/compiler/utils/atomic_dex_ref_map_test.cc b/compiler/utils/atomic_dex_ref_map_test.cc
index ae19a9c..8fce36f 100644
--- a/compiler/utils/atomic_dex_ref_map_test.cc
+++ b/compiler/utils/atomic_dex_ref_map_test.cc
@@ -31,40 +31,40 @@
   ScopedObjectAccess soa(Thread::Current());
   std::unique_ptr<const DexFile> dex(OpenTestDexFile("Interfaces"));
   ASSERT_TRUE(dex != nullptr);
-  using Map = AtomicDexRefMap<int>;
+  using Map = AtomicDexRefMap<MethodReference, int>;
   Map map;
   int value = 123;
   // Error case: Not already inserted.
-  EXPECT_FALSE(map.Get(DexFileReference(dex.get(), 1), &value));
+  EXPECT_FALSE(map.Get(MethodReference(dex.get(), 1), &value));
   EXPECT_FALSE(map.HaveDexFile(dex.get()));
   // Error case: Dex file not registered.
-  EXPECT_TRUE(map.Insert(DexFileReference(dex.get(), 1), 0, 1) == Map::kInsertResultInvalidDexFile);
-  map.AddDexFile(dex.get(), dex->NumMethodIds());
+  EXPECT_TRUE(map.Insert(MethodReference(dex.get(), 1), 0, 1) == Map::kInsertResultInvalidDexFile);
+  map.AddDexFile(dex.get());
   EXPECT_TRUE(map.HaveDexFile(dex.get()));
   EXPECT_GT(dex->NumMethodIds(), 10u);
   // After we have added the get should succeed but return the default value.
-  EXPECT_TRUE(map.Get(DexFileReference(dex.get(), 1), &value));
+  EXPECT_TRUE(map.Get(MethodReference(dex.get(), 1), &value));
   EXPECT_EQ(value, 0);
   // Actually insert an item and make sure we can retreive it.
   static const int kInsertValue = 44;
-  EXPECT_TRUE(map.Insert(DexFileReference(dex.get(), 1), 0, kInsertValue) ==
+  EXPECT_TRUE(map.Insert(MethodReference(dex.get(), 1), 0, kInsertValue) ==
               Map::kInsertResultSuccess);
-  EXPECT_TRUE(map.Get(DexFileReference(dex.get(), 1), &value));
+  EXPECT_TRUE(map.Get(MethodReference(dex.get(), 1), &value));
   EXPECT_EQ(value, kInsertValue);
   static const int kInsertValue2 = 123;
-  EXPECT_TRUE(map.Insert(DexFileReference(dex.get(), 2), 0, kInsertValue2) ==
+  EXPECT_TRUE(map.Insert(MethodReference(dex.get(), 2), 0, kInsertValue2) ==
               Map::kInsertResultSuccess);
-  EXPECT_TRUE(map.Get(DexFileReference(dex.get(), 1), &value));
+  EXPECT_TRUE(map.Get(MethodReference(dex.get(), 1), &value));
   EXPECT_EQ(value, kInsertValue);
-  EXPECT_TRUE(map.Get(DexFileReference(dex.get(), 2), &value));
+  EXPECT_TRUE(map.Get(MethodReference(dex.get(), 2), &value));
   EXPECT_EQ(value, kInsertValue2);
   // Error case: Incorrect expected value for CAS.
-  EXPECT_TRUE(map.Insert(DexFileReference(dex.get(), 1), 0, kInsertValue + 1) ==
+  EXPECT_TRUE(map.Insert(MethodReference(dex.get(), 1), 0, kInsertValue + 1) ==
       Map::kInsertResultCASFailure);
   // Correctly overwrite the value and verify.
-  EXPECT_TRUE(map.Insert(DexFileReference(dex.get(), 1), kInsertValue, kInsertValue + 1) ==
+  EXPECT_TRUE(map.Insert(MethodReference(dex.get(), 1), kInsertValue, kInsertValue + 1) ==
       Map::kInsertResultSuccess);
-  EXPECT_TRUE(map.Get(DexFileReference(dex.get(), 1), &value));
+  EXPECT_TRUE(map.Get(MethodReference(dex.get(), 1), &value));
   EXPECT_EQ(value, kInsertValue + 1);
 }
 
diff --git a/compiler/verifier_deps_test.cc b/compiler/verifier_deps_test.cc
index 5c097da..c706370 100644
--- a/compiler/verifier_deps_test.cc
+++ b/compiler/verifier_deps_test.cc
@@ -97,7 +97,7 @@
     callbacks_->SetVerifierDeps(nullptr);
     // Clear entries in the verification results to avoid hitting a DCHECK that
     // we always succeed inserting a new entry after verifying.
-    AtomicDexRefMap<const VerifiedMethod*>* map =
+    AtomicDexRefMap<MethodReference, const VerifiedMethod*>* map =
         &compiler_driver_->GetVerificationResults()->atomic_verified_methods_;
     map->Visit([](const DexFileReference& ref ATTRIBUTE_UNUSED, const VerifiedMethod* method) {
       delete method;