6684579: SoftReference processing can be made more efficient
Summary: For current soft-ref clearing policies, we can decide at marking time if a soft-reference will definitely not be cleared, postponing the decision of whether it will definitely be cleared to the final reference processing phase. This can be especially beneficial in the case of concurrent collectors where the marking is usually concurrent but reference processing is usually not.
Reviewed-by: jmasa
--- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp Thu Nov 20 12:27:41 2008 -0800
+++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp Thu Nov 20 16:56:09 2008 -0800
@@ -1961,6 +1961,7 @@
ref_processor()->set_enqueuing_is_done(false);
ref_processor()->enable_discovery();
+ ref_processor()->snap_policy(clear_all_soft_refs);
// If an asynchronous collection finishes, the _modUnionTable is
// all clear. If we are assuming the collection from an asynchronous
// collection, clear the _modUnionTable.
@@ -2384,6 +2385,9 @@
Universe::verify(true);
}
+ // Snapshot the soft reference policy to be used in this collection cycle.
+ ref_processor()->snap_policy(clear_all_soft_refs);
+
bool init_mark_was_synchronous = false; // until proven otherwise
while (_collectorState != Idling) {
if (TraceCMSState) {
@@ -4591,11 +4595,11 @@
if (!dirtyRegion.is_empty()) {
assert(numDirtyCards > 0, "consistency check");
HeapWord* stop_point = NULL;
+ stopTimer();
+ CMSTokenSyncWithLocks ts(true, gen->freelistLock(),
+ bitMapLock());
+ startTimer();
{
- stopTimer();
- CMSTokenSyncWithLocks ts(true, gen->freelistLock(),
- bitMapLock());
- startTimer();
verify_work_stacks_empty();
verify_overflow_empty();
sample_eden();
@@ -4612,10 +4616,6 @@
assert((CMSPermGenPrecleaningEnabled && (gen == _permGen)) ||
(_collectorState == AbortablePreclean && should_abort_preclean()),
"Unparsable objects should only be in perm gen.");
-
- stopTimer();
- CMSTokenSyncWithLocks ts(true, bitMapLock());
- startTimer();
_modUnionTable.mark_range(MemRegion(stop_point, dirtyRegion.end()));
if (should_abort_preclean()) {
break; // out of preclean loop
@@ -5678,23 +5678,14 @@
ResourceMark rm;
HandleMark hm;
- ReferencePolicy* soft_ref_policy;
-
- assert(!ref_processor()->enqueuing_is_done(), "Enqueuing should not be complete");
- // Process weak references.
- if (clear_all_soft_refs) {
- soft_ref_policy = new AlwaysClearPolicy();
- } else {
-#ifdef COMPILER2
- soft_ref_policy = new LRUMaxHeapPolicy();
-#else
- soft_ref_policy = new LRUCurrentHeapPolicy();
-#endif // COMPILER2
- }
- verify_work_stacks_empty();
ReferenceProcessor* rp = ref_processor();
assert(rp->span().equals(_span), "Spans should be equal");
+ assert(!rp->enqueuing_is_done(), "Enqueuing should not be complete");
+ // Process weak references.
+ rp->snap_policy(clear_all_soft_refs);
+ verify_work_stacks_empty();
+
CMSKeepAliveClosure cmsKeepAliveClosure(this, _span, &_markBitMap,
&_markStack, false /* !preclean */);
CMSDrainMarkingStackClosure cmsDrainMarkingStackClosure(this,
@@ -5704,14 +5695,12 @@
TraceTime t("weak refs processing", PrintGCDetails, false, gclog_or_tty);
if (rp->processing_is_mt()) {
CMSRefProcTaskExecutor task_executor(*this);
- rp->process_discovered_references(soft_ref_policy,
- &_is_alive_closure,
+ rp->process_discovered_references(&_is_alive_closure,
&cmsKeepAliveClosure,
&cmsDrainMarkingStackClosure,
&task_executor);
} else {
- rp->process_discovered_references(soft_ref_policy,
- &_is_alive_closure,
+ rp->process_discovered_references(&_is_alive_closure,
&cmsKeepAliveClosure,
&cmsDrainMarkingStackClosure,
NULL);
@@ -6166,8 +6155,8 @@
#endif
size_t CMSCollector::block_size_using_printezis_bits(HeapWord* addr) const {
- assert(_markBitMap.isMarked(addr) && _markBitMap.isMarked(addr + 1),
- "missing Printezis mark?");
+ assert(_markBitMap.isMarked(addr) && _markBitMap.isMarked(addr + 1),
+ "missing Printezis mark?");
HeapWord* nextOneAddr = _markBitMap.getNextMarkedWordAddress(addr + 2);
size_t size = pointer_delta(nextOneAddr + 1, addr);
assert(size == CompactibleFreeListSpace::adjustObjectSize(size),
--- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp Thu Nov 20 12:27:41 2008 -0800
+++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp Thu Nov 20 16:56:09 2008 -0800
@@ -811,6 +811,7 @@
ReferenceProcessor* rp = g1h->ref_processor();
rp->verify_no_references_recorded();
rp->enable_discovery(); // enable ("weak") refs discovery
+ rp->snap_policy(false); // snapshot the soft ref policy to be used in this cycle
SATBMarkQueueSet& satb_mq_set = JavaThread::satb_mark_queue_set();
satb_mq_set.set_process_completed_threshold(G1SATBProcessCompletedThreshold);
@@ -1829,32 +1830,21 @@
void ConcurrentMark::weakRefsWork(bool clear_all_soft_refs) {
ResourceMark rm;
HandleMark hm;
- ReferencePolicy* soft_ref_policy;
+ G1CollectedHeap* g1h = G1CollectedHeap::heap();
+ ReferenceProcessor* rp = g1h->ref_processor();
// Process weak references.
- if (clear_all_soft_refs) {
- soft_ref_policy = new AlwaysClearPolicy();
- } else {
-#ifdef COMPILER2
- soft_ref_policy = new LRUMaxHeapPolicy();
-#else
- soft_ref_policy = new LRUCurrentHeapPolicy();
-#endif
- }
+ rp->snap_policy(clear_all_soft_refs);
assert(_markStack.isEmpty(), "mark stack should be empty");
- G1CollectedHeap* g1 = G1CollectedHeap::heap();
- G1CMIsAliveClosure g1IsAliveClosure(g1);
-
- G1CMKeepAliveClosure g1KeepAliveClosure(g1, this, nextMarkBitMap());
+ G1CMIsAliveClosure g1IsAliveClosure (g1h);
+ G1CMKeepAliveClosure g1KeepAliveClosure(g1h, this, nextMarkBitMap());
G1CMDrainMarkingStackClosure
g1DrainMarkingStackClosure(nextMarkBitMap(), &_markStack,
&g1KeepAliveClosure);
// XXXYYY Also: copy the parallel ref processing code from CMS.
- ReferenceProcessor* rp = g1->ref_processor();
- rp->process_discovered_references(soft_ref_policy,
- &g1IsAliveClosure,
+ rp->process_discovered_references(&g1IsAliveClosure,
&g1KeepAliveClosure,
&g1DrainMarkingStackClosure,
NULL);
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Thu Nov 20 12:27:41 2008 -0800
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Thu Nov 20 16:56:09 2008 -0800
@@ -891,6 +891,7 @@
ReferenceProcessorIsAliveMutator rp_is_alive_null(ref_processor(), NULL);
ref_processor()->enable_discovery();
+ ref_processor()->snap_policy(clear_all_soft_refs);
// Do collection work
{
@@ -2463,7 +2464,7 @@
COMPILER2_PRESENT(DerivedPointerTable::clear());
- // We want to turn off ref discovere, if necessary, and turn it back on
+ // We want to turn off ref discovery, if necessary, and turn it back on
// on again later if we do.
bool was_enabled = ref_processor()->discovery_enabled();
if (was_enabled) ref_processor()->disable_discovery();
--- a/hotspot/src/share/vm/gc_implementation/g1/g1MarkSweep.cpp Thu Nov 20 12:27:41 2008 -0800
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1MarkSweep.cpp Thu Nov 20 16:56:09 2008 -0800
@@ -33,8 +33,9 @@
// hook up weak ref data so it can be used during Mark-Sweep
assert(GenMarkSweep::ref_processor() == NULL, "no stomping");
+ assert(rp != NULL, "should be non-NULL");
GenMarkSweep::_ref_processor = rp;
- assert(rp != NULL, "should be non-NULL");
+ rp->snap_policy(clear_all_softrefs);
// When collecting the permanent generation methodOops may be moving,
// so we either have to flush all bcp data or convert it into bci.
@@ -121,23 +122,12 @@
&GenMarkSweep::follow_root_closure);
// Process reference objects found during marking
- ReferencePolicy *soft_ref_policy;
- if (clear_all_softrefs) {
- soft_ref_policy = new AlwaysClearPolicy();
- } else {
-#ifdef COMPILER2
- soft_ref_policy = new LRUMaxHeapPolicy();
-#else
- soft_ref_policy = new LRUCurrentHeapPolicy();
-#endif
- }
- assert(soft_ref_policy != NULL,"No soft reference policy");
- GenMarkSweep::ref_processor()->process_discovered_references(
- soft_ref_policy,
- &GenMarkSweep::is_alive,
- &GenMarkSweep::keep_alive,
- &GenMarkSweep::follow_stack_closure,
- NULL);
+ ReferenceProcessor* rp = GenMarkSweep::ref_processor();
+ rp->snap_policy(clear_all_softrefs);
+ rp->process_discovered_references(&GenMarkSweep::is_alive,
+ &GenMarkSweep::keep_alive,
+ &GenMarkSweep::follow_stack_closure,
+ NULL);
// Follow system dictionary roots and unload classes
bool purged_class = SystemDictionary::do_unloading(&GenMarkSweep::is_alive);
--- a/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp Thu Nov 20 12:27:41 2008 -0800
+++ b/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp Thu Nov 20 16:56:09 2008 -0800
@@ -759,17 +759,12 @@
thread_state_set.steals(),
thread_state_set.pops()+thread_state_set.steals());
}
- assert(thread_state_set.pushes() == thread_state_set.pops() + thread_state_set.steals(),
+ assert(thread_state_set.pushes() == thread_state_set.pops()
+ + thread_state_set.steals(),
"Or else the queues are leaky.");
- // For now, process discovered weak refs sequentially.
-#ifdef COMPILER2
- ReferencePolicy *soft_ref_policy = new LRUMaxHeapPolicy();
-#else
- ReferencePolicy *soft_ref_policy = new LRUCurrentHeapPolicy();
-#endif // COMPILER2
-
// Process (weak) reference objects found during scavenge.
+ ReferenceProcessor* rp = ref_processor();
IsAliveClosure is_alive(this);
ScanWeakRefClosure scan_weak_ref(this);
KeepAliveClosure keep_alive(&scan_weak_ref);
@@ -778,18 +773,17 @@
set_promo_failure_scan_stack_closure(&scan_without_gc_barrier);
EvacuateFollowersClosureGeneral evacuate_followers(gch, _level,
&scan_without_gc_barrier, &scan_with_gc_barrier);
- if (ref_processor()->processing_is_mt()) {
+ rp->snap_policy(clear_all_soft_refs);
+ if (rp->processing_is_mt()) {
ParNewRefProcTaskExecutor task_executor(*this, thread_state_set);
- ref_processor()->process_discovered_references(
- soft_ref_policy, &is_alive, &keep_alive, &evacuate_followers,
- &task_executor);
+ rp->process_discovered_references(&is_alive, &keep_alive,
+ &evacuate_followers, &task_executor);
} else {
thread_state_set.flush();
gch->set_par_threads(0); // 0 ==> non-parallel.
gch->save_marks();
- ref_processor()->process_discovered_references(
- soft_ref_policy, &is_alive, &keep_alive, &evacuate_followers,
- NULL);
+ rp->process_discovered_references(&is_alive, &keep_alive,
+ &evacuate_followers, NULL);
}
if (!promotion_failed()) {
// Swap the survivor spaces.
@@ -851,14 +845,14 @@
SpecializationStats::print();
- ref_processor()->set_enqueuing_is_done(true);
- if (ref_processor()->processing_is_mt()) {
+ rp->set_enqueuing_is_done(true);
+ if (rp->processing_is_mt()) {
ParNewRefProcTaskExecutor task_executor(*this, thread_state_set);
- ref_processor()->enqueue_discovered_references(&task_executor);
+ rp->enqueue_discovered_references(&task_executor);
} else {
- ref_processor()->enqueue_discovered_references(NULL);
+ rp->enqueue_discovered_references(NULL);
}
- ref_processor()->verify_no_references_recorded();
+ rp->verify_no_references_recorded();
}
static int sum;
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp Thu Nov 20 12:27:41 2008 -0800
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp Thu Nov 20 16:56:09 2008 -0800
@@ -172,6 +172,7 @@
COMPILER2_PRESENT(DerivedPointerTable::clear());
ref_processor()->enable_discovery();
+ ref_processor()->snap_policy(clear_all_softrefs);
mark_sweep_phase1(clear_all_softrefs);
@@ -517,20 +518,9 @@
// Process reference objects found during marking
{
- ReferencePolicy *soft_ref_policy;
- if (clear_all_softrefs) {
- soft_ref_policy = new AlwaysClearPolicy();
- } else {
-#ifdef COMPILER2
- soft_ref_policy = new LRUMaxHeapPolicy();
-#else
- soft_ref_policy = new LRUCurrentHeapPolicy();
-#endif // COMPILER2
- }
- assert(soft_ref_policy != NULL,"No soft reference policy");
+ ref_processor()->snap_policy(clear_all_softrefs);
ref_processor()->process_discovered_references(
- soft_ref_policy, is_alive_closure(), mark_and_push_closure(),
- follow_stack_closure(), NULL);
+ is_alive_closure(), mark_and_push_closure(), follow_stack_closure(), NULL);
}
// Follow system dictionary roots and unload classes
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp Thu Nov 20 12:27:41 2008 -0800
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp Thu Nov 20 16:56:09 2008 -0800
@@ -1578,6 +1578,7 @@
COMPILER2_PRESENT(DerivedPointerTable::clear());
ref_processor()->enable_discovery();
+ ref_processor()->snap_policy(maximum_heap_compaction);
bool marked_for_unloading = false;
@@ -1894,26 +1895,14 @@
// Process reference objects found during marking
{
TraceTime tm_r("reference processing", print_phases(), true, gclog_or_tty);
- ReferencePolicy *soft_ref_policy;
- if (maximum_heap_compaction) {
- soft_ref_policy = new AlwaysClearPolicy();
- } else {
-#ifdef COMPILER2
- soft_ref_policy = new LRUMaxHeapPolicy();
-#else
- soft_ref_policy = new LRUCurrentHeapPolicy();
-#endif // COMPILER2
- }
- assert(soft_ref_policy != NULL, "No soft reference policy");
if (ref_processor()->processing_is_mt()) {
RefProcTaskExecutor task_executor;
ref_processor()->process_discovered_references(
- soft_ref_policy, is_alive_closure(), &mark_and_push_closure,
- &follow_stack_closure, &task_executor);
+ is_alive_closure(), &mark_and_push_closure, &follow_stack_closure,
+ &task_executor);
} else {
ref_processor()->process_discovered_references(
- soft_ref_policy, is_alive_closure(), &mark_and_push_closure,
- &follow_stack_closure, NULL);
+ is_alive_closure(), &mark_and_push_closure, &follow_stack_closure, NULL);
}
}
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp Thu Nov 20 12:27:41 2008 -0800
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp Thu Nov 20 16:56:09 2008 -0800
@@ -330,6 +330,7 @@
COMPILER2_PRESENT(DerivedPointerTable::clear());
reference_processor()->enable_discovery();
+ reference_processor()->snap_policy(false);
// We track how much was promoted to the next generation for
// the AdaptiveSizePolicy.
@@ -394,24 +395,16 @@
// Process reference objects discovered during scavenge
{
-#ifdef COMPILER2
- ReferencePolicy *soft_ref_policy = new LRUMaxHeapPolicy();
-#else
- ReferencePolicy *soft_ref_policy = new LRUCurrentHeapPolicy();
-#endif // COMPILER2
-
+ reference_processor()->snap_policy(false); // not always_clear
PSKeepAliveClosure keep_alive(promotion_manager);
PSEvacuateFollowersClosure evac_followers(promotion_manager);
- assert(soft_ref_policy != NULL,"No soft reference policy");
if (reference_processor()->processing_is_mt()) {
PSRefProcTaskExecutor task_executor;
reference_processor()->process_discovered_references(
- soft_ref_policy, &_is_alive_closure, &keep_alive, &evac_followers,
- &task_executor);
+ &_is_alive_closure, &keep_alive, &evac_followers, &task_executor);
} else {
reference_processor()->process_discovered_references(
- soft_ref_policy, &_is_alive_closure, &keep_alive, &evac_followers,
- NULL);
+ &_is_alive_closure, &keep_alive, &evac_followers, NULL);
}
}
--- a/hotspot/src/share/vm/includeDB_core Thu Nov 20 12:27:41 2008 -0800
+++ b/hotspot/src/share/vm/includeDB_core Thu Nov 20 16:56:09 2008 -0800
@@ -3434,6 +3434,7 @@
referenceProcessor.cpp systemDictionary.hpp
referenceProcessor.hpp instanceRefKlass.hpp
+referenceProcessor.hpp referencePolicy.hpp
reflection.cpp arguments.hpp
reflection.cpp handles.inline.hpp
--- a/hotspot/src/share/vm/memory/defNewGeneration.cpp Thu Nov 20 12:27:41 2008 -0800
+++ b/hotspot/src/share/vm/memory/defNewGeneration.cpp Thu Nov 20 16:56:09 2008 -0800
@@ -540,14 +540,6 @@
assert(gch->no_allocs_since_save_marks(0),
"save marks have not been newly set.");
- // Weak refs.
- // FIXME: Are these storage leaks, or are they resource objects?
-#ifdef COMPILER2
- ReferencePolicy *soft_ref_policy = new LRUMaxHeapPolicy();
-#else
- ReferencePolicy *soft_ref_policy = new LRUCurrentHeapPolicy();
-#endif // COMPILER2
-
// Not very pretty.
CollectorPolicy* cp = gch->collector_policy();
@@ -574,8 +566,10 @@
evacuate_followers.do_void();
FastKeepAliveClosure keep_alive(this, &scan_weak_ref);
- ref_processor()->process_discovered_references(
- soft_ref_policy, &is_alive, &keep_alive, &evacuate_followers, NULL);
+ ReferenceProcessor* rp = ref_processor();
+ rp->snap_policy(clear_all_soft_refs);
+ rp->process_discovered_references(&is_alive, &keep_alive, &evacuate_followers,
+ NULL);
if (!promotion_failed()) {
// Swap the survivor spaces.
eden()->clear(SpaceDecorator::Mangle);
--- a/hotspot/src/share/vm/memory/genCollectedHeap.cpp Thu Nov 20 12:27:41 2008 -0800
+++ b/hotspot/src/share/vm/memory/genCollectedHeap.cpp Thu Nov 20 16:56:09 2008 -0800
@@ -525,8 +525,9 @@
if (rp->discovery_is_atomic()) {
rp->verify_no_references_recorded();
rp->enable_discovery();
+ rp->snap_policy(clear_all_soft_refs);
} else {
- // collect() will enable discovery as appropriate
+ // collect() below will enable discovery as appropriate
}
_gens[i]->collect(full, clear_all_soft_refs, size, is_tlab);
if (!rp->enqueuing_is_done()) {
--- a/hotspot/src/share/vm/memory/genMarkSweep.cpp Thu Nov 20 12:27:41 2008 -0800
+++ b/hotspot/src/share/vm/memory/genMarkSweep.cpp Thu Nov 20 16:56:09 2008 -0800
@@ -31,8 +31,9 @@
// hook up weak ref data so it can be used during Mark-Sweep
assert(ref_processor() == NULL, "no stomping");
+ assert(rp != NULL, "should be non-NULL");
_ref_processor = rp;
- assert(rp != NULL, "should be non-NULL");
+ rp->snap_policy(clear_all_softrefs);
TraceTime t1("Full GC", PrintGC && !PrintGCDetails, true, gclog_or_tty);
@@ -245,20 +246,9 @@
// Process reference objects found during marking
{
- ReferencePolicy *soft_ref_policy;
- if (clear_all_softrefs) {
- soft_ref_policy = new AlwaysClearPolicy();
- } else {
-#ifdef COMPILER2
- soft_ref_policy = new LRUMaxHeapPolicy();
-#else
- soft_ref_policy = new LRUCurrentHeapPolicy();
-#endif // COMPILER2
- }
- assert(soft_ref_policy != NULL,"No soft reference policy");
+ ref_processor()->snap_policy(clear_all_softrefs);
ref_processor()->process_discovered_references(
- soft_ref_policy, &is_alive, &keep_alive,
- &follow_stack_closure, NULL);
+ &is_alive, &keep_alive, &follow_stack_closure, NULL);
}
// Follow system dictionary roots and unload classes
--- a/hotspot/src/share/vm/memory/referencePolicy.cpp Thu Nov 20 12:27:41 2008 -0800
+++ b/hotspot/src/share/vm/memory/referencePolicy.cpp Thu Nov 20 16:56:09 2008 -0800
@@ -26,6 +26,11 @@
# include "incls/_referencePolicy.cpp.incl"
LRUCurrentHeapPolicy::LRUCurrentHeapPolicy() {
+ snap();
+}
+
+// Capture state (of-the-VM) information needed to evaluate the policy
+void LRUCurrentHeapPolicy::snap() {
_max_interval = (Universe::get_heap_free_at_last_gc() / M) * SoftRefLRUPolicyMSPerMB;
assert(_max_interval >= 0,"Sanity check");
}
@@ -47,6 +52,11 @@
/////////////////////// MaxHeap //////////////////////
LRUMaxHeapPolicy::LRUMaxHeapPolicy() {
+ snap();
+}
+
+// Capture state (of-the-VM) information needed to evaluate the policy
+void LRUMaxHeapPolicy::snap() {
size_t max_heap = MaxHeapSize;
max_heap -= Universe::get_heap_used_at_last_gc();
max_heap /= M;
--- a/hotspot/src/share/vm/memory/referencePolicy.hpp Thu Nov 20 12:27:41 2008 -0800
+++ b/hotspot/src/share/vm/memory/referencePolicy.hpp Thu Nov 20 16:56:09 2008 -0800
@@ -26,9 +26,11 @@
// should be cleared.
-class ReferencePolicy : public ResourceObj {
+class ReferencePolicy : public CHeapObj {
public:
virtual bool should_clear_reference(oop p) { ShouldNotReachHere(); return true; }
+ // Capture state (of-the-VM) information needed to evaluate the policy
+ virtual void snap() { /* do nothing */ }
};
class NeverClearPolicy : public ReferencePolicy {
@@ -48,6 +50,8 @@
public:
LRUCurrentHeapPolicy();
+ // Capture state (of-the-VM) information needed to evaluate the policy
+ void snap();
bool should_clear_reference(oop p);
};
@@ -58,5 +62,7 @@
public:
LRUMaxHeapPolicy();
+ // Capture state (of-the-VM) information needed to evaluate the policy
+ void snap();
bool should_clear_reference(oop p);
};
--- a/hotspot/src/share/vm/memory/referenceProcessor.cpp Thu Nov 20 12:27:41 2008 -0800
+++ b/hotspot/src/share/vm/memory/referenceProcessor.cpp Thu Nov 20 16:56:09 2008 -0800
@@ -25,6 +25,11 @@
# include "incls/_precompiled.incl"
# include "incls/_referenceProcessor.cpp.incl"
+ReferencePolicy* ReferenceProcessor::_always_clear_soft_ref_policy = NULL;
+ReferencePolicy* ReferenceProcessor::_default_soft_ref_policy = NULL;
+oop ReferenceProcessor::_sentinelRef = NULL;
+const int subclasses_of_ref = REF_PHANTOM - REF_OTHER;
+
// List of discovered references.
class DiscoveredList {
public:
@@ -58,10 +63,6 @@
size_t _len;
};
-oop ReferenceProcessor::_sentinelRef = NULL;
-
-const int subclasses_of_ref = REF_PHANTOM - REF_OTHER;
-
void referenceProcessor_init() {
ReferenceProcessor::init_statics();
}
@@ -82,6 +83,12 @@
}
assert(_sentinelRef != NULL && _sentinelRef->is_oop(),
"Just constructed it!");
+ _always_clear_soft_ref_policy = new AlwaysClearPolicy();
+ _default_soft_ref_policy = new COMPILER2_PRESENT(LRUMaxHeapPolicy())
+ NOT_COMPILER2(LRUCurrentHeapPolicy());
+ if (_always_clear_soft_ref_policy == NULL || _default_soft_ref_policy == NULL) {
+ vm_exit_during_initialization("Could not allocate reference policy object");
+ }
guarantee(RefDiscoveryPolicy == ReferenceBasedDiscovery ||
RefDiscoveryPolicy == ReferentBasedDiscovery,
"Unrecongnized RefDiscoveryPolicy");
@@ -108,6 +115,7 @@
vm_exit_during_initialization("Could not allocate ReferenceProcessor object");
}
rp->set_is_alive_non_header(is_alive_non_header);
+ rp->snap_policy(false /* default soft ref policy */);
return rp;
}
@@ -194,7 +202,6 @@
}
void ReferenceProcessor::process_discovered_references(
- ReferencePolicy* policy,
BoolObjectClosure* is_alive,
OopClosure* keep_alive,
VoidClosure* complete_gc,
@@ -209,7 +216,7 @@
// Soft references
{
TraceTime tt("SoftReference", trace_time, false, gclog_or_tty);
- process_discovered_reflist(_discoveredSoftRefs, policy, true,
+ process_discovered_reflist(_discoveredSoftRefs, _current_soft_ref_policy, true,
is_alive, keep_alive, complete_gc, task_executor);
}
@@ -1092,15 +1099,28 @@
// reachable.
if (is_alive_non_header() != NULL) {
oop referent = java_lang_ref_Reference::referent(obj);
- // We'd like to assert the following:
- // assert(referent != NULL, "Refs with null referents already filtered");
- // However, since this code may be executed concurrently with
- // mutators, which can clear() the referent, it is not
- // guaranteed that the referent is non-NULL.
+ // In the case of non-concurrent discovery, the last
+ // disjunct below should hold. It may not hold in the
+ // case of concurrent discovery because mutators may
+ // concurrently clear() a Reference.
+ assert(UseConcMarkSweepGC || UseG1GC || referent != NULL,
+ "Refs with null referents already filtered");
if (is_alive_non_header()->do_object_b(referent)) {
return false; // referent is reachable
}
}
+ if (rt == REF_SOFT) {
+ // For soft refs we can decide now if these are not
+ // current candidates for clearing, in which case we
+ // can mark through them now, rather than delaying that
+ // to the reference-processing phase. Since all current
+ // time-stamp policies advance the soft-ref clock only
+ // at a major collection cycle, this is always currently
+ // accurate.
+ if (!_current_soft_ref_policy->should_clear_reference(obj)) {
+ return false;
+ }
+ }
HeapWord* const discovered_addr = java_lang_ref_Reference::discovered_addr(obj);
const oop discovered = java_lang_ref_Reference::discovered(obj);
--- a/hotspot/src/share/vm/memory/referenceProcessor.hpp Thu Nov 20 12:27:41 2008 -0800
+++ b/hotspot/src/share/vm/memory/referenceProcessor.hpp Thu Nov 20 16:56:09 2008 -0800
@@ -23,7 +23,7 @@
*/
// ReferenceProcessor class encapsulates the per-"collector" processing
-// of "weak" references for GC. The interface is useful for supporting
+// of java.lang.Reference objects for GC. The interface is useful for supporting
// a generational abstraction, in particular when there are multiple
// generations that are being independently collected -- possibly
// concurrently and/or incrementally. Note, however, that the
@@ -75,6 +75,14 @@
// all collectors but the CMS collector).
BoolObjectClosure* _is_alive_non_header;
+ // Soft ref clearing policies
+ // . the default policy
+ static ReferencePolicy* _default_soft_ref_policy;
+ // . the "clear all" policy
+ static ReferencePolicy* _always_clear_soft_ref_policy;
+ // . the current policy below is either one of the above
+ ReferencePolicy* _current_soft_ref_policy;
+
// The discovered ref lists themselves
// The MT'ness degree of the queues below
@@ -90,6 +98,12 @@
DiscoveredList* discovered_soft_refs() { return _discoveredSoftRefs; }
static oop sentinel_ref() { return _sentinelRef; }
static oop* adr_sentinel_ref() { return &_sentinelRef; }
+ ReferencePolicy* snap_policy(bool always_clear) {
+ _current_soft_ref_policy = always_clear ?
+ _always_clear_soft_ref_policy : _default_soft_ref_policy;
+ _current_soft_ref_policy->snap(); // snapshot the policy threshold
+ return _current_soft_ref_policy;
+ }
public:
// Process references with a certain reachability level.
@@ -297,8 +311,7 @@
bool discover_reference(oop obj, ReferenceType rt);
// Process references found during GC (called by the garbage collector)
- void process_discovered_references(ReferencePolicy* policy,
- BoolObjectClosure* is_alive,
+ void process_discovered_references(BoolObjectClosure* is_alive,
OopClosure* keep_alive,
VoidClosure* complete_gc,
AbstractRefProcTaskExecutor* task_executor);
--- a/hotspot/src/share/vm/memory/universe.cpp Thu Nov 20 12:27:41 2008 -0800
+++ b/hotspot/src/share/vm/memory/universe.cpp Thu Nov 20 16:56:09 2008 -0800
@@ -96,7 +96,7 @@
bool Universe::_fully_initialized = false;
size_t Universe::_heap_capacity_at_last_gc;
-size_t Universe::_heap_used_at_last_gc;
+size_t Universe::_heap_used_at_last_gc = 0;
CollectedHeap* Universe::_collectedHeap = NULL;
address Universe::_heap_base = NULL;
--- a/hotspot/src/share/vm/utilities/macros.hpp Thu Nov 20 12:27:41 2008 -0800
+++ b/hotspot/src/share/vm/utilities/macros.hpp Thu Nov 20 16:56:09 2008 -0800
@@ -65,8 +65,10 @@
// COMPILER2 variant
#ifdef COMPILER2
#define COMPILER2_PRESENT(code) code
+#define NOT_COMPILER2(code)
#else // COMPILER2
#define COMPILER2_PRESENT(code)
+#define NOT_COMPILER2(code) code
#endif // COMPILER2