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/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);
 }