Simplify CHA dependency tracking data structure.

Change pointer to vector in the map to just vector.

Bug: 37953217
Test: m -j20 test-art-host-run-test test-art-host-gtest
Change-Id: I0e601c69aef99401360cc1a3967c056952a05a0f
diff --git a/runtime/cha.cc b/runtime/cha.cc
index 7948c29..e6bdb84 100644
--- a/runtime/cha.cc
+++ b/runtime/cha.cc
@@ -31,34 +31,24 @@
 void ClassHierarchyAnalysis::AddDependency(ArtMethod* method,
                                            ArtMethod* dependent_method,
                                            OatQuickMethodHeader* dependent_header) {
-  auto it = cha_dependency_map_.find(method);
-  if (it == cha_dependency_map_.end()) {
-    cha_dependency_map_[method] =
-        new std::vector<std::pair<art::ArtMethod*, art::OatQuickMethodHeader*>>();
-    it = cha_dependency_map_.find(method);
-  } else {
-    DCHECK(it->second != nullptr);
-  }
-  it->second->push_back(std::make_pair(dependent_method, dependent_header));
+  const auto it = cha_dependency_map_.insert(
+      decltype(cha_dependency_map_)::value_type(method, ListOfDependentPairs())).first;
+  it->second.push_back({dependent_method, dependent_header});
 }
 
-std::vector<std::pair<ArtMethod*, OatQuickMethodHeader*>>*
-    ClassHierarchyAnalysis::GetDependents(ArtMethod* method) {
+static const ClassHierarchyAnalysis::ListOfDependentPairs s_empty_vector;
+
+const ClassHierarchyAnalysis::ListOfDependentPairs& ClassHierarchyAnalysis::GetDependents(
+    ArtMethod* method) {
   auto it = cha_dependency_map_.find(method);
   if (it != cha_dependency_map_.end()) {
-    DCHECK(it->second != nullptr);
     return it->second;
   }
-  return nullptr;
+  return s_empty_vector;
 }
 
-void ClassHierarchyAnalysis::RemoveDependencyFor(ArtMethod* method) {
-  auto it = cha_dependency_map_.find(method);
-  if (it != cha_dependency_map_.end()) {
-    auto dependents = it->second;
-    cha_dependency_map_.erase(it);
-    delete dependents;
-  }
+void ClassHierarchyAnalysis::RemoveAllDependenciesFor(ArtMethod* method) {
+  cha_dependency_map_.erase(method);
 }
 
 void ClassHierarchyAnalysis::RemoveDependentsWithMethodHeaders(
@@ -66,20 +56,19 @@
   // Iterate through all entries in the dependency map and remove any entry that
   // contains one of those in method_headers.
   for (auto map_it = cha_dependency_map_.begin(); map_it != cha_dependency_map_.end(); ) {
-    auto dependents = map_it->second;
-    for (auto vec_it = dependents->begin(); vec_it != dependents->end(); ) {
-      OatQuickMethodHeader* method_header = vec_it->second;
-      auto it = std::find(method_headers.begin(), method_headers.end(), method_header);
-      if (it != method_headers.end()) {
-        vec_it = dependents->erase(vec_it);
-      } else {
-        vec_it++;
-      }
-    }
+    ListOfDependentPairs& dependents = map_it->second;
+    dependents.erase(
+        std::remove_if(
+            dependents.begin(),
+            dependents.end(),
+            [&method_headers](MethodAndMethodHeaderPair& dependent) {
+              return method_headers.find(dependent.second) != method_headers.end();
+            }),
+        dependents.end());
+
     // Remove the map entry if there are no more dependents.
-    if (dependents->empty()) {
+    if (dependents.empty()) {
       map_it = cha_dependency_map_.erase(map_it);
-      delete dependents;
     } else {
       map_it++;
     }
@@ -554,11 +543,7 @@
         }
 
         // Invalidate all dependents.
-        auto dependents = GetDependents(invalidated);
-        if (dependents == nullptr) {
-          continue;
-        }
-        for (const auto& dependent : *dependents) {
+        for (const auto& dependent : GetDependents(invalidated)) {
           ArtMethod* method = dependent.first;;
           OatQuickMethodHeader* method_header = dependent.second;
           VLOG(class_linker) << "CHA invalidated compiled code for " << method->PrettyMethod();
@@ -567,7 +552,7 @@
               method, method_header);
           dependent_method_headers.insert(method_header);
         }
-        RemoveDependencyFor(invalidated);
+        RemoveAllDependenciesFor(invalidated);
       }
     }
 
diff --git a/runtime/cha.h b/runtime/cha.h
index 99c49d2..d9692a6 100644
--- a/runtime/cha.h
+++ b/runtime/cha.h
@@ -94,12 +94,11 @@
                      OatQuickMethodHeader* dependent_header) REQUIRES(Locks::cha_lock_);
 
   // Return compiled code that assumes that `method` has single-implementation.
-  std::vector<MethodAndMethodHeaderPair>* GetDependents(ArtMethod* method)
-      REQUIRES(Locks::cha_lock_);
+  const ListOfDependentPairs& GetDependents(ArtMethod* method) REQUIRES(Locks::cha_lock_);
 
   // Remove dependency tracking for compiled code that assumes that
   // `method` has single-implementation.
-  void RemoveDependencyFor(ArtMethod* method) REQUIRES(Locks::cha_lock_);
+  void RemoveAllDependenciesFor(ArtMethod* method) REQUIRES(Locks::cha_lock_);
 
   // Remove from cha_dependency_map_ all entries that contain OatQuickMethodHeader from
   // the given `method_headers` set.
@@ -158,7 +157,7 @@
 
   // A map that maps a method to a set of compiled code that assumes that method has a
   // single implementation, which is used to do CHA-based devirtualization.
-  std::unordered_map<ArtMethod*, ListOfDependentPairs*> cha_dependency_map_
+  std::unordered_map<ArtMethod*, ListOfDependentPairs> cha_dependency_map_
     GUARDED_BY(Locks::cha_lock_);
 
   DISALLOW_COPY_AND_ASSIGN(ClassHierarchyAnalysis);
diff --git a/runtime/cha_test.cc b/runtime/cha_test.cc
index d2f335e..c60720f 100644
--- a/runtime/cha_test.cc
+++ b/runtime/cha_test.cc
@@ -36,58 +36,58 @@
   ClassHierarchyAnalysis cha;
   MutexLock cha_mu(Thread::Current(), *Locks::cha_lock_);
 
-  ASSERT_EQ(cha.GetDependents(METHOD1), nullptr);
-  ASSERT_EQ(cha.GetDependents(METHOD2), nullptr);
-  ASSERT_EQ(cha.GetDependents(METHOD3), nullptr);
+  ASSERT_TRUE(cha.GetDependents(METHOD1).empty());
+  ASSERT_TRUE(cha.GetDependents(METHOD2).empty());
+  ASSERT_TRUE(cha.GetDependents(METHOD3).empty());
 
   cha.AddDependency(METHOD1, METHOD2, METHOD_HEADER2);
-  ASSERT_EQ(cha.GetDependents(METHOD2), nullptr);
-  ASSERT_EQ(cha.GetDependents(METHOD3), nullptr);
+  ASSERT_TRUE(cha.GetDependents(METHOD2).empty());
+  ASSERT_TRUE(cha.GetDependents(METHOD3).empty());
   auto dependents = cha.GetDependents(METHOD1);
-  ASSERT_EQ(dependents->size(), 1u);
-  ASSERT_EQ(dependents->at(0).first, METHOD2);
-  ASSERT_EQ(dependents->at(0).second, METHOD_HEADER2);
+  ASSERT_EQ(dependents.size(), 1u);
+  ASSERT_EQ(dependents[0].first, METHOD2);
+  ASSERT_EQ(dependents[0].second, METHOD_HEADER2);
 
   cha.AddDependency(METHOD1, METHOD3, METHOD_HEADER3);
-  ASSERT_EQ(cha.GetDependents(METHOD2), nullptr);
-  ASSERT_EQ(cha.GetDependents(METHOD3), nullptr);
+  ASSERT_TRUE(cha.GetDependents(METHOD2).empty());
+  ASSERT_TRUE(cha.GetDependents(METHOD3).empty());
   dependents = cha.GetDependents(METHOD1);
-  ASSERT_EQ(dependents->size(), 2u);
-  ASSERT_EQ(dependents->at(0).first, METHOD2);
-  ASSERT_EQ(dependents->at(0).second, METHOD_HEADER2);
-  ASSERT_EQ(dependents->at(1).first, METHOD3);
-  ASSERT_EQ(dependents->at(1).second, METHOD_HEADER3);
+  ASSERT_EQ(dependents.size(), 2u);
+  ASSERT_EQ(dependents[0].first, METHOD2);
+  ASSERT_EQ(dependents[0].second, METHOD_HEADER2);
+  ASSERT_EQ(dependents[1].first, METHOD3);
+  ASSERT_EQ(dependents[1].second, METHOD_HEADER3);
 
   std::unordered_set<OatQuickMethodHeader*> headers;
   headers.insert(METHOD_HEADER2);
   cha.RemoveDependentsWithMethodHeaders(headers);
-  ASSERT_EQ(cha.GetDependents(METHOD2), nullptr);
-  ASSERT_EQ(cha.GetDependents(METHOD3), nullptr);
+  ASSERT_TRUE(cha.GetDependents(METHOD2).empty());
+  ASSERT_TRUE(cha.GetDependents(METHOD3).empty());
   dependents = cha.GetDependents(METHOD1);
-  ASSERT_EQ(dependents->size(), 1u);
-  ASSERT_EQ(dependents->at(0).first, METHOD3);
-  ASSERT_EQ(dependents->at(0).second, METHOD_HEADER3);
+  ASSERT_EQ(dependents.size(), 1u);
+  ASSERT_EQ(dependents[0].first, METHOD3);
+  ASSERT_EQ(dependents[0].second, METHOD_HEADER3);
 
   cha.AddDependency(METHOD2, METHOD1, METHOD_HEADER1);
-  ASSERT_EQ(cha.GetDependents(METHOD3), nullptr);
+  ASSERT_TRUE(cha.GetDependents(METHOD3).empty());
   dependents = cha.GetDependents(METHOD1);
-  ASSERT_EQ(dependents->size(), 1u);
+  ASSERT_EQ(dependents.size(), 1u);
   dependents = cha.GetDependents(METHOD2);
-  ASSERT_EQ(dependents->size(), 1u);
+  ASSERT_EQ(dependents.size(), 1u);
 
   headers.insert(METHOD_HEADER3);
   cha.RemoveDependentsWithMethodHeaders(headers);
-  ASSERT_EQ(cha.GetDependents(METHOD1), nullptr);
-  ASSERT_EQ(cha.GetDependents(METHOD3), nullptr);
+  ASSERT_TRUE(cha.GetDependents(METHOD1).empty());
+  ASSERT_TRUE(cha.GetDependents(METHOD3).empty());
   dependents = cha.GetDependents(METHOD2);
-  ASSERT_EQ(dependents->size(), 1u);
-  ASSERT_EQ(dependents->at(0).first, METHOD1);
-  ASSERT_EQ(dependents->at(0).second, METHOD_HEADER1);
+  ASSERT_EQ(dependents.size(), 1u);
+  ASSERT_EQ(dependents[0].first, METHOD1);
+  ASSERT_EQ(dependents[0].second, METHOD_HEADER1);
 
-  cha.RemoveDependencyFor(METHOD2);
-  ASSERT_EQ(cha.GetDependents(METHOD1), nullptr);
-  ASSERT_EQ(cha.GetDependents(METHOD2), nullptr);
-  ASSERT_EQ(cha.GetDependents(METHOD3), nullptr);
+  cha.RemoveAllDependenciesFor(METHOD2);
+  ASSERT_TRUE(cha.GetDependents(METHOD1).empty());
+  ASSERT_TRUE(cha.GetDependents(METHOD2).empty());
+  ASSERT_TRUE(cha.GetDependents(METHOD3).empty());
 }
 
 }  // namespace art