hotspot/src/share/vm/memory/referenceProcessor.cpp
changeset 1606 dcf9714addbe
parent 1605 6b43d186eb8d
child 1610 5dddd195cc86
--- 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);