diff options
author | 2023-06-12 10:38:55 +0100 | |
---|---|---|
committer | 2023-07-10 11:57:06 +0000 | |
commit | e61fbd8bac612d2c0b7bfe4c1bfef13a6fe526cb (patch) | |
tree | 2581315e39c6297b5fd9fbd0e77103cdd5d375c6 /runtime/class_linker.cc | |
parent | b57e01e9ff980644cc98da5b775453453c948c1a (diff) |
Add a phony BootClassLoader instance to hold the boot class table.
This allows using the regular card table mechanism for aging.
Test: test.py
(cherry picked from https://android-review.googlesource.com/q/commit:e9c9704218de4683fdc6946cdca17a692c14bdca)
Merged-In: I36d8ccb3c9fdbe6747af3b076bc4aab8a7df657c
Change-Id: I36d8ccb3c9fdbe6747af3b076bc4aab8a7df657c
Diffstat (limited to 'runtime/class_linker.cc')
-rw-r--r-- | runtime/class_linker.cc | 79 |
1 files changed, 30 insertions, 49 deletions
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc index 9aa29b8a44..8e44acf52c 100644 --- a/runtime/class_linker.cc +++ b/runtime/class_linker.cc @@ -184,6 +184,18 @@ static ObjPtr<mirror::Object> GetErroneousStateError(ObjPtr<mirror::Class> c) } } +static void WriteBarrierOnClassLoader(ObjPtr<mirror::ClassLoader> class_loader) + REQUIRES_SHARED(Locks::mutator_lock_) { + if (class_loader != nullptr) { + WriteBarrier::ForEveryFieldWrite(class_loader); + return; + } + ObjPtr<mirror::ClassLoader> boot_loader = Runtime::Current()->GetBootClassLoaderInstance(); + if (boot_loader != nullptr) { + WriteBarrier::ForEveryFieldWrite(boot_loader); + } +} + static bool IsVerifyError(ObjPtr<mirror::Object> obj) REQUIRES_SHARED(Locks::mutator_lock_) { // This is slow, but we only use it for rethrowing an error, and for DCHECK. @@ -1005,7 +1017,7 @@ bool ClassLinker::InitWithoutImage(std::vector<std::unique_ptr<const DexFile>> b FinishInit(self); - VLOG(startup) << "ClassLinker::InitFromCompiler exiting"; + VLOG(startup) << "ClassLinker::InitWithoutImage exiting"; return true; } @@ -2376,27 +2388,6 @@ void ClassLinker::VisitClassRoots(RootVisitor* visitor, VisitRootFlags flags) { kVisitRootFlagStopLoggingNewRoots)); } if ((flags & kVisitRootFlagAllRoots) != 0) { - // Argument for how root visiting deals with ArtField and ArtMethod roots. - // There is 3 GC cases to handle: - // Non moving concurrent: - // This case is easy to handle since the reference members of ArtMethod and ArtFields are held - // live by the class and class roots. - // - // Moving non-concurrent: - // This case needs to call visit VisitNativeRoots in case the classes or dex cache arrays move. - // To prevent missing roots, this case needs to ensure that there is no - // suspend points between the point which we allocate ArtMethod arrays and place them in a - // class which is in the class table. - // - // Moving concurrent: - // Need to make sure to not copy ArtMethods without doing read barriers since the roots are - // marked concurrently and we don't hold the classlinker_classes_lock_ when we do the copy. - // - // Use an unbuffered visitor since the class table uses a temporary GcRoot for holding decoded - // ClassTable::TableSlot. The buffered root visiting would access a stale stack location for - // these objects. - UnbufferedRootVisitor root_visitor(visitor, RootInfo(kRootStickyClass)); - boot_class_table_->VisitRoots(root_visitor); // If tracing is enabled, then mark all the class loaders to prevent unloading. if ((flags & kVisitRootFlagClassLoader) != 0 || tracing_enabled) { gc::Heap* const heap = Runtime::Current()->GetHeap(); @@ -3279,7 +3270,7 @@ ObjPtr<mirror::Class> ClassLinker::FindClass(Thread* self, old = result_ptr; // For the comparison below, after releasing the lock. if (descriptor_equals) { class_table->InsertWithHash(result_ptr, hash); - WriteBarrier::ForEveryFieldWrite(class_loader.Get()); + WriteBarrierOnClassLoader(class_loader.Get()); } // else throw below, after releasing the lock. } } @@ -4109,11 +4100,9 @@ void ClassLinker::RegisterDexFileLocked(const DexFile& dex_file, data.class_table->InsertStrongRoot(dex_cache); // Make sure that the dex cache holds the classloader live. dex_cache->SetClassLoader(class_loader); - if (class_loader != nullptr) { - // Since we added a strong root to the class table, do the write barrier as required for - // remembered sets and generational GCs. - WriteBarrier::ForEveryFieldWrite(class_loader); - } + // Since we added a strong root to the class table, do the write barrier as required for + // remembered sets and generational GCs. + WriteBarrierOnClassLoader(class_loader); bool inserted = dex_caches_.emplace(&dex_file, std::move(data)).second; CHECK(inserted); } @@ -4161,11 +4150,9 @@ void ClassLinker::RegisterExistingDexCache(ObjPtr<mirror::DexCache> dex_cache, WriterMutexLock mu(self, *Locks::dex_lock_); RegisterDexFileLocked(*dex_file, h_dex_cache.Get(), h_class_loader.Get()); table->InsertStrongRoot(h_dex_cache.Get()); - if (h_class_loader.Get() != nullptr) { - // Since we added a strong root to the class table, do the write barrier as required for - // remembered sets and generational GCs. - WriteBarrier::ForEveryFieldWrite(h_class_loader.Get()); - } + // Since we added a strong root to the class table, do the write barrier as required for + // remembered sets and generational GCs. + WriteBarrierOnClassLoader(h_class_loader.Get()); } static void ThrowDexFileAlreadyRegisteredError(Thread* self, const DexFile& dex_file) @@ -4251,11 +4238,9 @@ ObjPtr<mirror::DexCache> ClassLinker::RegisterDexFile(const DexFile& dex_file, return nullptr; } table->InsertStrongRoot(h_dex_cache.Get()); - if (h_class_loader.Get() != nullptr) { - // Since we added a strong root to the class table, do the write barrier as required for - // remembered sets and generational GCs. - WriteBarrier::ForEveryFieldWrite(h_class_loader.Get()); - } + // Since we added a strong root to the class table, do the write barrier as required for + // remembered sets and generational GCs. + WriteBarrierOnClassLoader(h_class_loader.Get()); VLOG(class_linker) << "Registered dex file " << dex_file.GetLocation(); PaletteNotifyDexFileLoaded(dex_file.GetLocation().c_str()); return h_dex_cache.Get(); @@ -4565,10 +4550,8 @@ ObjPtr<mirror::Class> ClassLinker::InsertClass(const char* descriptor, } VerifyObject(klass); class_table->InsertWithHash(klass, hash); - if (class_loader != nullptr) { - // This is necessary because we need to have the card dirtied for remembered sets. - WriteBarrier::ForEveryFieldWrite(class_loader); - } + // This is necessary because we need to have the card dirtied for remembered sets. + WriteBarrierOnClassLoader(class_loader); if (log_new_roots_) { new_class_roots_.push_back(GcRoot<mirror::Class>(klass)); } @@ -6240,11 +6223,9 @@ bool ClassLinker::LinkClass(Thread* self, ClassTable* const table = InsertClassTableForClassLoader(class_loader); const ObjPtr<mirror::Class> existing = table->UpdateClass(descriptor, h_new_class.Get(), ComputeModifiedUtf8Hash(descriptor)); - if (class_loader != nullptr) { - // We updated the class in the class table, perform the write barrier so that the GC knows - // about the change. - WriteBarrier::ForEveryFieldWrite(class_loader); - } + // We updated the class in the class table, perform the write barrier so that the GC knows + // about the change. + WriteBarrierOnClassLoader(class_loader); CHECK_EQ(existing, klass.Get()); if (log_new_roots_) { new_class_roots_.push_back(GcRoot<mirror::Class>(h_new_class.Get())); @@ -10779,10 +10760,10 @@ void ClassLinker::InsertDexFileInToClassLoader(ObjPtr<mirror::Object> dex_file, WriterMutexLock mu(self, *Locks::classlinker_classes_lock_); ClassTable* const table = ClassTableForClassLoader(class_loader); DCHECK(table != nullptr); - if (table->InsertStrongRoot(dex_file) && class_loader != nullptr) { + if (table->InsertStrongRoot(dex_file)) { // It was not already inserted, perform the write barrier to let the GC know the class loader's // class table was modified. - WriteBarrier::ForEveryFieldWrite(class_loader); + WriteBarrierOnClassLoader(class_loader); } } |