< prev index next >

src/hotspot/share/gc/shared/referenceProcessor.hpp

Print this page
rev 49912 : imported patch 8201492-properly-implement-non-contiguous-reference-processing
rev 49913 : imported patch 8201492-stefanj-review
rev 49914 : [mq]: 8201492-kim-review

@@ -36,22 +36,17 @@
 
 // ReferenceProcessor class encapsulates the per-"collector" processing
 // 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
+// concurrently and/or incrementally.
 // ReferenceProcessor class abstracts away from a generational setting
-// by using only a heap interval (called "span" below), thus allowing
-// its use in a straightforward manner in a general, non-generational
-// setting.
+// by using a closure that determines whether a given reference or referent are
+// subject to this ReferenceProcessor's discovery, thus allowing its use in a
+// straightforward manner in a general, non-generational, non-contiguous generation
+// (or heap) setting.
 //
-// The basic idea is that each ReferenceProcessor object concerns
-// itself with ("weak") reference processing in a specific "span"
-// of the heap of interest to a specific collector. Currently,
-// the span is a convex interval of the heap, but, efficiency
-// apart, there seems to be no reason it couldn't be extended
-// (with appropriate modifications) to any "non-convex interval".
 
 // forward references
 class ReferencePolicy;
 class AbstractRefProcTaskExecutor;
 

@@ -166,20 +161,18 @@
     NOT_PRODUCT(_processed++);
   }
 };
 
 class ReferenceProcessor : public ReferenceDiscoverer {
-
- private:
   size_t total_count(DiscoveredList lists[]) const;
 
- protected:
   // The SoftReference master timestamp clock
   static jlong _soft_ref_timestamp_clock;
 
-  MemRegion   _span;                    // (right-open) interval of heap
-                                        // subject to wkref discovery
+  BoolObjectClosure* _is_subject_to_discovery; // determines whether a given oop is subject
+                                               // to this ReferenceProcessor's discovery
+                                               // (and further processing).
 
   bool        _discovering_refs;        // true when discovery enabled
   bool        _discovery_is_atomic;     // if discovery is atomic wrt
                                         // other collectors in configuration
   bool        _discovery_is_mt;         // true if reference discovery is MT.

@@ -255,23 +248,14 @@
                       BoolObjectClosure*  is_alive,
                       OopClosure*         keep_alive,
                       VoidClosure*        complete_gc);
   // Phase2: remove all those references whose referents are
   // reachable.
-  inline void process_phase2(DiscoveredList&    refs_list,
+  void process_phase2(DiscoveredList&    refs_list,
                              BoolObjectClosure* is_alive,
                              OopClosure*        keep_alive,
-                             VoidClosure*       complete_gc) {
-    if (discovery_is_atomic()) {
-      // complete_gc is ignored in this case for this phase
-      pp2_work(refs_list, is_alive, keep_alive);
-    } else {
-      assert(complete_gc != NULL, "Error");
-      pp2_work_concurrent_discovery(refs_list, is_alive,
-                                    keep_alive, complete_gc);
-    }
-  }
+                      VoidClosure*       complete_gc);
   // Work methods in support of process_phase2
   void pp2_work(DiscoveredList&    refs_list,
                 BoolObjectClosure* is_alive,
                 OopClosure*        keep_alive);
   void pp2_work_concurrent_discovery(

@@ -310,20 +294,19 @@
   const char* list_name(uint i);
 
   void enqueue_discovered_reflists(AbstractRefProcTaskExecutor* task_executor,
                                    ReferenceProcessorPhaseTimes* phase_times);
 
- protected:
   // "Preclean" the given discovered reference list
   // by removing references with strongly reachable referents.
   // Currently used in support of CMS only.
   void preclean_discovered_reflist(DiscoveredList&    refs_list,
                                    BoolObjectClosure* is_alive,
                                    OopClosure*        keep_alive,
                                    VoidClosure*       complete_gc,
                                    YieldClosure*      yield);
-
+private:
   // round-robin mod _num_q (not: _not_ mode _max_num_q)
   uint next_id() {
     uint id = _next_id;
     assert(!_discovery_is_mt, "Round robin should only be used in serial discovery");
     if (++_next_id == _num_q) {

@@ -344,13 +327,15 @@
   void balance_queues(DiscoveredList ref_lists[]);
 
   // Update (advance) the soft ref master clock field.
   void update_soft_ref_master_clock();
 
- public:
+  bool is_subject_to_discovery(oop const obj) const;
+
+public:
   // Default parameters give you a vanilla reference processor.
-  ReferenceProcessor(MemRegion span,
+  ReferenceProcessor(BoolObjectClosure* is_subject_to_discovery,
                      bool mt_processing = false, uint mt_processing_degree = 1,
                      bool mt_discovery  = false, uint mt_discovery_degree  = 1,
                      bool atomic_discovery = true,
                      BoolObjectClosure* is_alive_non_header = NULL);
 

@@ -371,13 +356,12 @@
   }
   void set_is_alive_non_header(BoolObjectClosure* is_alive_non_header) {
     _is_alive_non_header = is_alive_non_header;
   }
 
-  // get and set span
-  MemRegion span()                   { return _span; }
-  void      set_span(MemRegion span) { _span = span; }
+  BoolObjectClosure* is_subject_to_discovery_closure() const { return _is_subject_to_discovery; }
+  void set_is_subject_to_discovery_closure(BoolObjectClosure* cl) { _is_subject_to_discovery = cl; }
 
   // start and stop weak ref discovery
   void enable_discovery(bool check_no_refs = true);
   void disable_discovery()  { _discovering_refs = false; }
   bool discovery_enabled()  { return _discovering_refs;  }

@@ -433,10 +417,30 @@
   // debugging
   void verify_no_references_recorded() PRODUCT_RETURN;
   void verify_referent(oop obj)        PRODUCT_RETURN;
 };
 
+// A subject-to-discovery closure that uses a single memory span to determine the area that
+// is subject to discovery. Useful for collectors which have contiguous generations.
+class SpanSubjectToDiscoveryClosure : public BoolObjectClosure {
+  MemRegion _span;
+
+public:
+  SpanSubjectToDiscoveryClosure() : BoolObjectClosure(), _span() { }
+  SpanSubjectToDiscoveryClosure(MemRegion span) : BoolObjectClosure(), _span(span) { }
+
+  MemRegion span() const { return _span; }
+
+  void set_span(MemRegion mr) {
+    _span = mr;
+  }
+
+  virtual bool do_object_b(oop obj) {
+    return _span.contains(obj);
+  }
+};
+
 // A utility class to disable reference discovery in
 // the scope which contains it, for given ReferenceProcessor.
 class NoRefDiscovery: StackObj {
  private:
   ReferenceProcessor* _rp;

@@ -454,28 +458,47 @@
       _rp->enable_discovery(false /*check_no_refs*/);
     }
   }
 };
 
+// A utility class to temporarily mutate the subject discovery closure of the
+// given ReferenceProcessor in the scope that contains it.
+class ReferenceProcessorSubjectToDiscoveryMutator : StackObj {
+  ReferenceProcessor* _rp;
+  BoolObjectClosure* _saved_cl;
+
+public:
+  ReferenceProcessorSubjectToDiscoveryMutator(ReferenceProcessor* rp, BoolObjectClosure* cl):
+    _rp(rp) {
+    _saved_cl = _rp->is_subject_to_discovery_closure();
+    _rp->set_is_subject_to_discovery_closure(cl);
+  }
+
+  ~ReferenceProcessorSubjectToDiscoveryMutator() {
+    _rp->set_is_subject_to_discovery_closure(_saved_cl);
+  }
+};
 
 // A utility class to temporarily mutate the span of the
 // given ReferenceProcessor in the scope that contains it.
-class ReferenceProcessorSpanMutator: StackObj {
- private:
+class ReferenceProcessorSpanMutator : StackObj {
   ReferenceProcessor* _rp;
-  MemRegion           _saved_span;
+  SpanSubjectToDiscoveryClosure _discoverer;
+  BoolObjectClosure* _old_discoverer;
 
- public:
+public:
   ReferenceProcessorSpanMutator(ReferenceProcessor* rp,
                                 MemRegion span):
-    _rp(rp) {
-    _saved_span = _rp->span();
-    _rp->set_span(span);
+    _rp(rp),
+    _discoverer(span),
+    _old_discoverer(rp->is_subject_to_discovery_closure()) {
+
+    rp->set_is_subject_to_discovery_closure(&_discoverer);
   }
 
   ~ReferenceProcessorSpanMutator() {
-    _rp->set_span(_saved_span);
+    _rp->set_is_subject_to_discovery_closure(_old_discoverer);
   }
 };
 
 // A utility class to temporarily change the MT'ness of
 // reference discovery for the given ReferenceProcessor

@@ -496,11 +519,10 @@
   ~ReferenceProcessorMTDiscoveryMutator() {
     _rp->set_mt_discovery(_saved_mt);
   }
 };
 
-
 // A utility class to temporarily change the disposition
 // of the "is_alive_non_header" closure field of the
 // given ReferenceProcessor in the scope that contains it.
 class ReferenceProcessorIsAliveMutator: StackObj {
  private:
< prev index next >