dex2oat: Faster class pruning.
Test: m test-art-host-gtest
Test: testrunner.py --host --optimizing
Bug: 181943478
Change-Id: I0f4facc13ded5e5a5755fe9bec1c32449049129a
diff --git a/dex2oat/linker/image_writer.cc b/dex2oat/linker/image_writer.cc
index 51daa30..c0dea85 100644
--- a/dex2oat/linker/image_writer.cc
+++ b/dex2oat/linker/image_writer.cc
@@ -1108,12 +1108,20 @@
size_t Prune() REQUIRES_SHARED(Locks::mutator_lock_) {
ClassTable* class_table =
Runtime::Current()->GetClassLinker()->ClassTableForClassLoader(class_loader_);
+ WriterMutexLock mu(Thread::Current(), class_table->lock_);
for (mirror::Class* klass : classes_to_prune_) {
- std::string storage;
- const char* descriptor = klass->GetDescriptor(&storage);
- bool result = class_table->Remove(descriptor);
- DCHECK(result);
- DCHECK(!class_table->Remove(descriptor)) << descriptor;
+ uint32_t hash = ClassTable::TableSlot::HashDescriptor(klass);
+ DCHECK(!class_table->classes_.empty());
+ ClassTable::ClassSet& last_class_set = class_table->classes_.back();
+ auto it = last_class_set.FindWithHash(ClassTable::TableSlot(klass, hash), hash);
+ DCHECK(it != last_class_set.end());
+ last_class_set.erase(it);
+ DCHECK(std::none_of(class_table->classes_.begin(),
+ class_table->classes_.end(),
+ [klass, hash](ClassTable::ClassSet& class_set) {
+ ClassTable::TableSlot slot(klass, hash);
+ return class_set.FindWithHash(slot, hash) != class_set.end();
+ }));
}
return defined_class_count_;
}
diff --git a/runtime/class_table.cc b/runtime/class_table.cc
index acfbcb0..4bc2fe6 100644
--- a/runtime/class_table.cc
+++ b/runtime/class_table.cc
@@ -153,19 +153,6 @@
classes_.back().InsertWithHash(TableSlot(klass, hash), hash);
}
-bool ClassTable::Remove(const char* descriptor) {
- DescriptorHashPair pair(descriptor, ComputeModifiedUtf8Hash(descriptor));
- WriterMutexLock mu(Thread::Current(), lock_);
- for (ClassSet& class_set : classes_) {
- auto it = class_set.find(pair);
- if (it != class_set.end()) {
- class_set.erase(it);
- return true;
- }
- }
- return false;
-}
-
bool ClassTable::InsertStrongRoot(ObjPtr<mirror::Object> obj) {
WriterMutexLock mu(Thread::Current(), lock_);
DCHECK(obj != nullptr);
diff --git a/runtime/class_table.h b/runtime/class_table.h
index 4c5fc62..3377f14 100644
--- a/runtime/class_table.h
+++ b/runtime/class_table.h
@@ -220,11 +220,6 @@
REQUIRES(!lock_)
REQUIRES_SHARED(Locks::mutator_lock_);
- // Returns true if the class was found and removed, false otherwise.
- bool Remove(const char* descriptor)
- REQUIRES(!lock_)
- REQUIRES_SHARED(Locks::mutator_lock_);
-
// Return true if we inserted the strong root, false if it already exists.
bool InsertStrongRoot(ObjPtr<mirror::Object> obj)
REQUIRES(!lock_)
diff --git a/runtime/class_table_test.cc b/runtime/class_table_test.cc
index d9f53ed..7dbeba5 100644
--- a/runtime/class_table_test.cc
+++ b/runtime/class_table_test.cc
@@ -137,12 +137,7 @@
});
EXPECT_EQ(classes.size(), 1u);
- // Test remove.
- table.Remove(descriptor_x);
- EXPECT_TRUE(table.LookupByDescriptor(h_X.Get()) == nullptr);
-
// Test that reading a class set from memory works.
- table.Insert(h_X.Get());
ClassTable::ClassSet temp_set;
table.Visit([&temp_set](ObjPtr<mirror::Class> klass) REQUIRES_SHARED(Locks::mutator_lock_) {
temp_set.insert(ClassTable::TableSlot(klass));