diff options
| -rw-r--r-- | runtime/runtime.cc | 32 |
1 files changed, 28 insertions, 4 deletions
diff --git a/runtime/runtime.cc b/runtime/runtime.cc index ccbd929acc..eaeda04256 100644 --- a/runtime/runtime.cc +++ b/runtime/runtime.cc @@ -3299,11 +3299,28 @@ void Runtime::ResetStartupCompleted() { startup_completed_.store(false, std::memory_order_seq_cst); } -class UnlinkStartupDexCacheVisitor : public DexCacheVisitor { +class CollectStartupDexCacheVisitor : public DexCacheVisitor { public: + explicit CollectStartupDexCacheVisitor(VariableSizedHandleScope& handles) : handles_(handles) {} + void Visit(ObjPtr<mirror::DexCache> dex_cache) REQUIRES_SHARED(Locks::dex_lock_, Locks::mutator_lock_) override { - dex_cache->UnlinkStartupCaches(); + handles_.NewHandle(dex_cache); + } + + private: + VariableSizedHandleScope& handles_; +}; + +class UnlinkVisitor { + public: + UnlinkVisitor() {} + + void VisitRootIfNonNull(StackReference<mirror::Object>* ref) + REQUIRES_SHARED(Locks::mutator_lock_) { + if (!ref->IsNull()) { + ref->AsMirrorPtr()->AsDexCache()->UnlinkStartupCaches(); + } } }; @@ -3321,9 +3338,10 @@ class Runtime::NotifyStartupCompletedTask : public gc::HeapTask { ScopedTrace trace("Releasing dex caches and app image spaces metadata"); ScopedObjectAccess soa(Thread::Current()); + // Collect dex caches that were allocated with the startup linear alloc. + VariableSizedHandleScope handles(soa.Self()); { - // Unlink dex caches that were allocated with the startup linear alloc. - UnlinkStartupDexCacheVisitor visitor; + CollectStartupDexCacheVisitor visitor(handles); ReaderMutexLock mu(self, *Locks::dex_lock_); runtime->GetClassLinker()->VisitDexCaches(&visitor); } @@ -3341,6 +3359,12 @@ class Runtime::NotifyStartupCompletedTask : public gc::HeapTask { gc::ScopedInterruptibleGCCriticalSection sigcs(self, gc::kGcCauseRunEmptyCheckpoint, gc::kCollectorTypeCriticalSection); + // Do the unlinking of dex cache arrays in the GC critical section to + // avoid GC not seeing these arrays. We do it before the checkpoint so + // we know after the checkpoint, no thread is holding onto the array. + UnlinkVisitor visitor; + handles.VisitRoots(visitor); + runtime->GetThreadList()->RunEmptyCheckpoint(); } |