Revert "Revert "Make sure that const-class linkage is preserved.""
Fix jdwp getting multiple instances of the same class.
Fix counting "zygote"/"non-zygote" classes in class table.
Fix FindClass() to EnsureResolved() classes added by
a racing thread to the class table.
Test: m test-art-host
Test: art/tools/run-jdwp-tests.sh --mode=host --variant=X64 --debug
Bug: 30627598
This reverts commit ecffc67068a28d55d131553bf915fdb9fafbbc03.
Change-Id: I15807949da4f163c2693fac2fbfc274f17685f8a
diff --git a/compiler/image_writer.cc b/compiler/image_writer.cc
index a706697..0f41cbf 100644
--- a/compiler/image_writer.cc
+++ b/compiler/image_writer.cc
@@ -838,19 +838,64 @@
return true;
}
-class ImageWriter::NonImageClassesVisitor : public ClassVisitor {
+class ImageWriter::PruneClassesVisitor : public ClassVisitor {
public:
- explicit NonImageClassesVisitor(ImageWriter* image_writer) : image_writer_(image_writer) {}
+ PruneClassesVisitor(ImageWriter* image_writer, ObjPtr<mirror::ClassLoader> class_loader)
+ : image_writer_(image_writer),
+ class_loader_(class_loader),
+ classes_to_prune_(),
+ defined_class_count_(0u) { }
- bool operator()(ObjPtr<Class> klass) OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_) {
+ bool operator()(ObjPtr<mirror::Class> klass) OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_) {
if (!image_writer_->KeepClass(klass.Ptr())) {
classes_to_prune_.insert(klass.Ptr());
+ if (klass->GetClassLoader() == class_loader_) {
+ ++defined_class_count_;
+ }
}
return true;
}
- std::unordered_set<mirror::Class*> classes_to_prune_;
+ size_t Prune() REQUIRES_SHARED(Locks::mutator_lock_) {
+ ClassTable* class_table =
+ Runtime::Current()->GetClassLinker()->ClassTableForClassLoader(class_loader_);
+ for (mirror::Class* klass : classes_to_prune_) {
+ std::string storage;
+ const char* descriptor = klass->GetDescriptor(&storage);
+ bool result = class_table->Remove(descriptor);
+ DCHECK(result);
+ }
+ return defined_class_count_;
+ }
+
+ private:
ImageWriter* const image_writer_;
+ const ObjPtr<mirror::ClassLoader> class_loader_;
+ std::unordered_set<mirror::Class*> classes_to_prune_;
+ size_t defined_class_count_;
+};
+
+class ImageWriter::PruneClassLoaderClassesVisitor : public ClassLoaderVisitor {
+ public:
+ explicit PruneClassLoaderClassesVisitor(ImageWriter* image_writer)
+ : image_writer_(image_writer), removed_class_count_(0) {}
+
+ virtual void Visit(ObjPtr<mirror::ClassLoader> class_loader) OVERRIDE
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ PruneClassesVisitor classes_visitor(image_writer_, class_loader);
+ ClassTable* class_table =
+ Runtime::Current()->GetClassLinker()->ClassTableForClassLoader(class_loader);
+ class_table->Visit(classes_visitor);
+ removed_class_count_ += classes_visitor.Prune();
+ }
+
+ size_t GetRemovedClassCount() const {
+ return removed_class_count_;
+ }
+
+ private:
+ ImageWriter* const image_writer_;
+ size_t removed_class_count_;
};
void ImageWriter::PruneNonImageClasses() {
@@ -862,21 +907,13 @@
// path dex caches.
class_linker->ClearClassTableStrongRoots();
- // Make a list of classes we would like to prune.
- NonImageClassesVisitor visitor(this);
- class_linker->VisitClasses(&visitor);
-
// Remove the undesired classes from the class roots.
- VLOG(compiler) << "Pruning " << visitor.classes_to_prune_.size() << " classes";
- for (mirror::Class* klass : visitor.classes_to_prune_) {
- std::string temp;
- const char* name = klass->GetDescriptor(&temp);
- VLOG(compiler) << "Pruning class " << name;
- if (!compile_app_image_) {
- DCHECK(IsBootClassLoaderClass(klass));
- }
- bool result = class_linker->RemoveClass(name, klass->GetClassLoader());
- DCHECK(result);
+ {
+ ReaderMutexLock mu(self, *Locks::classlinker_classes_lock_);
+ PruneClassLoaderClassesVisitor class_loader_visitor(this);
+ class_loader_visitor.Visit(nullptr); // Visit boot class loader.
+ class_linker->VisitClassLoaders(&class_loader_visitor);
+ VLOG(compiler) << "Pruned " << class_loader_visitor.GetRemovedClassCount() << " classes";
}
// Clear references to removed classes from the DexCaches.
@@ -1507,8 +1544,10 @@
}
// Calculate the size of the class table.
ReaderMutexLock mu(self, *Locks::classlinker_classes_lock_);
- DCHECK_EQ(image_info.class_table_->NumZygoteClasses(), 0u);
- if (image_info.class_table_->NumNonZygoteClasses() != 0u) {
+ CHECK_EQ(class_loaders_.size(), compile_app_image_ ? 1u : 0u);
+ mirror::ClassLoader* class_loader = compile_app_image_ ? *class_loaders_.begin() : nullptr;
+ DCHECK_EQ(image_info.class_table_->NumZygoteClasses(class_loader), 0u);
+ if (image_info.class_table_->NumNonZygoteClasses(class_loader) != 0u) {
image_info.class_table_bytes_ += image_info.class_table_->WriteToMemory(nullptr);
}
}
@@ -1853,8 +1892,10 @@
// above comment for intern tables.
ClassTable temp_class_table;
temp_class_table.ReadFromMemory(class_table_memory_ptr);
- CHECK_EQ(temp_class_table.NumZygoteClasses(), table->NumNonZygoteClasses() +
- table->NumZygoteClasses());
+ CHECK_EQ(class_loaders_.size(), compile_app_image_ ? 1u : 0u);
+ mirror::ClassLoader* class_loader = compile_app_image_ ? *class_loaders_.begin() : nullptr;
+ CHECK_EQ(temp_class_table.NumZygoteClasses(class_loader),
+ table->NumNonZygoteClasses(class_loader) + table->NumZygoteClasses(class_loader));
BufferedRootVisitor<kDefaultBufferedRootCount> buffered_visitor(&root_visitor,
RootInfo(kRootUnknown));
temp_class_table.VisitRoots(buffered_visitor);
diff --git a/compiler/image_writer.h b/compiler/image_writer.h
index 24fad46..ad6ffd8 100644
--- a/compiler/image_writer.h
+++ b/compiler/image_writer.h
@@ -588,7 +588,8 @@
class FixupVisitor;
class GetRootsVisitor;
class NativeLocationVisitor;
- class NonImageClassesVisitor;
+ class PruneClassesVisitor;
+ class PruneClassLoaderClassesVisitor;
class VisitReferencesVisitor;
DISALLOW_COPY_AND_ASSIGN(ImageWriter);