diff options
-rw-r--r-- | runtime/cha.cc | 61 | ||||
-rw-r--r-- | runtime/cha.h | 7 | ||||
-rw-r--r-- | runtime/cha_test.cc | 64 |
3 files changed, 58 insertions, 74 deletions
diff --git a/runtime/cha.cc b/runtime/cha.cc index 7948c29e5d..e6bdb84d4c 100644 --- a/runtime/cha.cc +++ b/runtime/cha.cc @@ -31,34 +31,24 @@ namespace art { 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 @@ void ClassHierarchyAnalysis::RemoveDependentsWithMethodHeaders( // 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 @@ void ClassHierarchyAnalysis::InvalidateSingleImplementationMethods( } // 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 @@ void ClassHierarchyAnalysis::InvalidateSingleImplementationMethods( method, method_header); dependent_method_headers.insert(method_header); } - RemoveDependencyFor(invalidated); + RemoveAllDependenciesFor(invalidated); } } diff --git a/runtime/cha.h b/runtime/cha.h index 99c49d2bca..d9692a684e 100644 --- a/runtime/cha.h +++ b/runtime/cha.h @@ -94,12 +94,11 @@ class ClassHierarchyAnalysis { 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 @@ class ClassHierarchyAnalysis { // 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 d2f335e951..c60720f4d3 100644 --- a/runtime/cha_test.cc +++ b/runtime/cha_test.cc @@ -36,58 +36,58 @@ TEST_F(CHATest, CHACheckDependency) { 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 |