summaryrefslogtreecommitdiff
path: root/runtime/gc/reference_processor.h
diff options
context:
space:
mode:
author Hans Boehm <hboehm@google.com> 2021-07-02 12:33:57 -0700
committer Hans Boehm <hboehm@google.com> 2022-01-26 01:46:16 +0000
commit0ab5b6d2afbdd71a18f8fb9b1fcf39e54cfd55a5 (patch)
tree03fcab756651cca711e042012a6d78cbab44c0e4 /runtime/gc/reference_processor.h
parentef879d49881c895deb5f4eb1b3cd20733189ca1c (diff)
Reduce pauses for weak reference access
Remove the "preserve references" machinery. Instead let the reference processor inform GetReferent about its state, so that it can leverage knowledge about whether reachable memory has in fact been completely marked. Restructure the ReferenceProcessor interface by adding Setup to ensure that ReferenceProcessor fields are properly set up before we disable the normal fast path through GetReferent. For the CC collector, forward essentially all SoftReferences as part of normal marking, so we don't stall weak reference access for those. Note briefly in the log if we encounter References that are only reachable from finalizers. SS and MS collectors are only minimally updated to keep them working. We now block in GetReferent only for the hopefully very brief period of marking objects that were initially missed as a result of a mutator collector race. This should hopefully eliminate multi-millisecond delays here. For 2043-reference-pauses from aosp/1952438, it reduces blocking from over 100 msecs to under 1 on host. This is mostly due to the better SoftReference treatment; 100 msec pauses in GetReferent() were never near-typical. We iteratively mark through SoftReferences now. Previously we could mistakenly clear SoftReferences discovered while marking from the top level ones. (Lokesh pointed this out.) To make this work, we change ForwardSoftReferences to actually remove References from the queue, as the comment always said it did. This also somewhat prepares us for a much less complete solution for pauses to access WeakGlobalRefs or other "system weaks". This fixes a memory ordering issue for the per-thread weak reference access flags used with the CC collector. I think the issue is still there for the CMS collector. That requires further discussion. Bug: 190867430 Bug: 189738006 Bug: 211784084 Test: Build and boot aosp & Treehugger; aosp/195243 Change-Id: I02f12ac481db4c4e400d253662a7a126318d4bec
Diffstat (limited to 'runtime/gc/reference_processor.h')
-rw-r--r--runtime/gc/reference_processor.h43
1 files changed, 28 insertions, 15 deletions
diff --git a/runtime/gc/reference_processor.h b/runtime/gc/reference_processor.h
index 51c50544bf..0f84211a87 100644
--- a/runtime/gc/reference_processor.h
+++ b/runtime/gc/reference_processor.h
@@ -46,19 +46,29 @@ class Heap;
class ReferenceProcessor {
public:
ReferenceProcessor();
- void ProcessReferences(bool concurrent,
- TimingLogger* timings,
- bool clear_soft_references,
- gc::collector::GarbageCollector* collector)
+
+ // Initialize for a reference processing pass. Called before suspending weak
+ // access.
+ void Setup(Thread* self,
+ collector::GarbageCollector* collector,
+ bool concurrent,
+ bool clear_soft_references)
+ REQUIRES(!Locks::reference_processor_lock_);
+ // Enqueue all types of java.lang.ref.References, and mark through finalizers.
+ // Assumes there is no concurrent mutator-driven marking, i.e. all potentially
+ // mutator-accessible objects should be marked before this.
+ void ProcessReferences(Thread* self, TimingLogger* timings)
REQUIRES_SHARED(Locks::mutator_lock_)
REQUIRES(Locks::heap_bitmap_lock_)
REQUIRES(!Locks::reference_processor_lock_);
+
// The slow path bool is contained in the reference class object, can only be set once
// Only allow setting this with mutators suspended so that we can avoid using a lock in the
// GetReferent fast path as an optimization.
void EnableSlowPath() REQUIRES_SHARED(Locks::mutator_lock_);
void BroadcastForSlowPath(Thread* self);
- // Decode the referent, may block if references are being processed.
+ // Decode the referent, may block if references are being processed. In the normal
+ // no-read-barrier or Baker-read-barrier cases, we assume reference is not a PhantomReference.
ObjPtr<mirror::Object> GetReferent(Thread* self, ObjPtr<mirror::Reference> reference)
REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Locks::reference_processor_lock_);
// Collects the cleared references and returns a task, to be executed after FinishGC, that will
@@ -78,27 +88,30 @@ class ReferenceProcessor {
void ClearReferent(ObjPtr<mirror::Reference> ref)
REQUIRES_SHARED(Locks::mutator_lock_)
REQUIRES(!Locks::reference_processor_lock_);
+ uint32_t ForwardSoftReferences(TimingLogger* timings)
+ REQUIRES_SHARED(Locks::mutator_lock_);
private:
bool SlowPathEnabled() REQUIRES_SHARED(Locks::mutator_lock_);
// Called by ProcessReferences.
void DisableSlowPath(Thread* self) REQUIRES(Locks::reference_processor_lock_)
REQUIRES_SHARED(Locks::mutator_lock_);
- // If we are preserving references it means that some dead objects may become live, we use start
- // and stop preserving to block mutators using GetReferrent from getting access to these
- // referents.
- void StartPreservingReferences(Thread* self) REQUIRES(!Locks::reference_processor_lock_);
- void StopPreservingReferences(Thread* self) REQUIRES(!Locks::reference_processor_lock_);
// Wait until reference processing is done.
void WaitUntilDoneProcessingReferences(Thread* self)
REQUIRES_SHARED(Locks::mutator_lock_)
REQUIRES(Locks::reference_processor_lock_);
// Collector which is clearing references, used by the GetReferent to return referents which are
- // already marked.
- collector::GarbageCollector* collector_ GUARDED_BY(Locks::reference_processor_lock_);
- // Boolean for whether or not we are preserving references (either soft references or finalizers).
- // If this is true, then we cannot return a referent (see comment in GetReferent).
- bool preserving_references_ GUARDED_BY(Locks::reference_processor_lock_);
+ // already marked. Only updated by thread currently running GC.
+ // Guarded by reference_processor_lock_ when not read by collector. Only the collector changes
+ // it.
+ collector::GarbageCollector* collector_;
+ // Reference processor state. Only valid while weak reference processing is suspended.
+ // Used by GetReferent and friends to return early.
+ enum class RpState : uint8_t { kStarting, kInitMarkingDone, kInitClearingDone };
+ RpState rp_state_ GUARDED_BY(Locks::reference_processor_lock_);
+ bool concurrent_; // Running concurrently with mutator? Only used by GC thread.
+ bool clear_soft_references_; // Only used by GC thread.
+
// Condition that people wait on if they attempt to get the referent of a reference while
// processing is in progress. Broadcast when an empty checkpoint is requested, but not for other
// checkpoints or thread suspensions. See mutator_gc_coord.md.