hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/cmsOopClosures.hpp
changeset 1 489c9b5090e2
child 360 21d113ecbf6a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/cmsOopClosures.hpp	Sat Dec 01 00:00:00 2007 +0000
@@ -0,0 +1,334 @@
+/*
+ * Copyright (c) 2007 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ */
+
+/////////////////////////////////////////////////////////////////
+// Closures used by ConcurrentMarkSweepGeneration's collector
+/////////////////////////////////////////////////////////////////
+class ConcurrentMarkSweepGeneration;
+class CMSBitMap;
+class CMSMarkStack;
+class CMSCollector;
+template<class E> class GenericTaskQueue;
+typedef GenericTaskQueue<oop> OopTaskQueue;
+template<class E> class GenericTaskQueueSet;
+typedef GenericTaskQueueSet<oop> OopTaskQueueSet;
+class MarkFromRootsClosure;
+class Par_MarkFromRootsClosure;
+
+class MarkRefsIntoClosure: public OopsInGenClosure {
+  const MemRegion    _span;
+  CMSBitMap*         _bitMap;
+  const bool         _should_do_nmethods;
+ public:
+  MarkRefsIntoClosure(MemRegion span, CMSBitMap* bitMap,
+                      bool should_do_nmethods);
+  void do_oop(oop* p);
+  void do_oop_nv(oop* p) { MarkRefsIntoClosure::do_oop(p); }
+  bool do_header() { return true; }
+  virtual const bool do_nmethods() const {
+    return _should_do_nmethods;
+  }
+  Prefetch::style prefetch_style() {
+    return Prefetch::do_read;
+  }
+};
+
+// A variant of the above used in certain kinds of CMS
+// marking verification.
+class MarkRefsIntoVerifyClosure: public OopsInGenClosure {
+  const MemRegion    _span;
+  CMSBitMap*         _verification_bm;
+  CMSBitMap*         _cms_bm;
+  const bool         _should_do_nmethods;
+ public:
+  MarkRefsIntoVerifyClosure(MemRegion span, CMSBitMap* verification_bm,
+                            CMSBitMap* cms_bm, bool should_do_nmethods);
+  void do_oop(oop* p);
+  void do_oop_nv(oop* p) { MarkRefsIntoVerifyClosure::do_oop(p); }
+  bool do_header() { return true; }
+  virtual const bool do_nmethods() const {
+    return _should_do_nmethods;
+  }
+  Prefetch::style prefetch_style() {
+    return Prefetch::do_read;
+  }
+};
+
+
+// The non-parallel version (the parallel version appears further below).
+class PushAndMarkClosure: public OopClosure {
+  CMSCollector*    _collector;
+  MemRegion        _span;
+  CMSBitMap*       _bit_map;
+  CMSBitMap*       _mod_union_table;
+  CMSMarkStack*    _mark_stack;
+  CMSMarkStack*    _revisit_stack;
+  bool             _concurrent_precleaning;
+  bool     const   _should_remember_klasses;
+ public:
+  PushAndMarkClosure(CMSCollector* collector,
+                     MemRegion span,
+                     ReferenceProcessor* rp,
+                     CMSBitMap* bit_map,
+                     CMSBitMap* mod_union_table,
+                     CMSMarkStack*  mark_stack,
+                     CMSMarkStack*  revisit_stack,
+                     bool           concurrent_precleaning);
+
+  void do_oop(oop* p);
+  void do_oop_nv(oop* p)  { PushAndMarkClosure::do_oop(p); }
+  bool do_header() { return true; }
+  Prefetch::style prefetch_style() {
+    return Prefetch::do_read;
+  }
+  const bool should_remember_klasses() const {
+    return _should_remember_klasses;
+  }
+  void remember_klass(Klass* k);
+};
+
+// In the parallel case, the revisit stack, the bit map and the
+// reference processor are currently all shared. Access to
+// these shared mutable structures must use appropriate
+// synchronization (for instance, via CAS). The marking stack
+// used in the non-parallel case above is here replaced with
+// an OopTaskQueue structure to allow efficient work stealing.
+class Par_PushAndMarkClosure: public OopClosure {
+  CMSCollector*    _collector;
+  MemRegion        _span;
+  CMSBitMap*       _bit_map;
+  OopTaskQueue*    _work_queue;
+  CMSMarkStack*    _revisit_stack;
+  bool     const   _should_remember_klasses;
+ public:
+  Par_PushAndMarkClosure(CMSCollector* collector,
+                         MemRegion span,
+                         ReferenceProcessor* rp,
+                         CMSBitMap* bit_map,
+                         OopTaskQueue* work_queue,
+                         CMSMarkStack* revisit_stack);
+
+  void do_oop(oop* p);
+  void do_oop_nv(oop* p)  { Par_PushAndMarkClosure::do_oop(p); }
+  bool do_header() { return true; }
+  Prefetch::style prefetch_style() {
+    return Prefetch::do_read;
+  }
+  const bool should_remember_klasses() const {
+    return _should_remember_klasses;
+  }
+  void remember_klass(Klass* k);
+};
+
+
+// The non-parallel version (the parallel version appears further below).
+class MarkRefsIntoAndScanClosure: public OopsInGenClosure {
+  MemRegion                  _span;
+  CMSBitMap*                 _bit_map;
+  CMSMarkStack*              _mark_stack;
+  PushAndMarkClosure         _pushAndMarkClosure;
+  CMSCollector*              _collector;
+  bool                       _yield;
+  // Whether closure is being used for concurrent precleaning
+  bool                       _concurrent_precleaning;
+  Mutex*                     _freelistLock;
+ public:
+  MarkRefsIntoAndScanClosure(MemRegion span,
+                             ReferenceProcessor* rp,
+                             CMSBitMap* bit_map,
+                             CMSBitMap* mod_union_table,
+                             CMSMarkStack*  mark_stack,
+                             CMSMarkStack*  revisit_stack,
+                             CMSCollector* collector,
+                             bool should_yield,
+                             bool concurrent_precleaning);
+  void do_oop(oop* p);
+  void do_oop_nv(oop* p) { MarkRefsIntoAndScanClosure::do_oop(p); }
+  bool do_header() { return true; }
+  virtual const bool do_nmethods() const { return true; }
+  Prefetch::style prefetch_style() {
+    return Prefetch::do_read;
+  }
+  void set_freelistLock(Mutex* m) {
+    _freelistLock = m;
+  }
+
+ private:
+  inline void do_yield_check();
+  void do_yield_work();
+  bool take_from_overflow_list();
+};
+
+// Tn this, the parallel avatar of MarkRefsIntoAndScanClosure, the revisit
+// stack and the bitMap are shared, so access needs to be suitably
+// sycnhronized. An OopTaskQueue structure, supporting efficient
+// workstealing, replaces a CMSMarkStack for storing grey objects.
+class Par_MarkRefsIntoAndScanClosure: public OopsInGenClosure {
+  MemRegion                      _span;
+  CMSBitMap*                     _bit_map;
+  OopTaskQueue*                  _work_queue;
+  const uint                     _low_water_mark;
+  Par_PushAndMarkClosure         _par_pushAndMarkClosure;
+ public:
+  Par_MarkRefsIntoAndScanClosure(CMSCollector* collector,
+                                 MemRegion span,
+                                 ReferenceProcessor* rp,
+                                 CMSBitMap* bit_map,
+                                 OopTaskQueue* work_queue,
+                                 CMSMarkStack*  revisit_stack);
+  void do_oop(oop* p);
+  void do_oop_nv(oop* p) { Par_MarkRefsIntoAndScanClosure::do_oop(p); }
+  bool do_header() { return true; }
+  virtual const bool do_nmethods() const { return true; }
+  Prefetch::style prefetch_style() {
+    return Prefetch::do_read;
+  }
+  void trim_queue(uint size);
+};
+
+// This closure is used during the concurrent marking phase
+// following the first checkpoint. Its use is buried in
+// the closure MarkFromRootsClosure.
+class PushOrMarkClosure: public OopClosure {
+  CMSCollector*    _collector;
+  MemRegion        _span;
+  CMSBitMap*       _bitMap;
+  CMSMarkStack*    _markStack;
+  CMSMarkStack*    _revisitStack;
+  HeapWord* const  _finger;
+  MarkFromRootsClosure* const _parent;
+  bool                  const _should_remember_klasses;
+ public:
+  PushOrMarkClosure(CMSCollector* cms_collector,
+                    MemRegion span,
+                    CMSBitMap* bitMap,
+                    CMSMarkStack*  markStack,
+                    CMSMarkStack*  revisitStack,
+                    HeapWord*      finger,
+                    MarkFromRootsClosure* parent);
+  void do_oop(oop* p);
+  void do_oop_nv(oop* p)  { PushOrMarkClosure::do_oop(p); }
+  const bool should_remember_klasses() const {
+    return _should_remember_klasses;
+  }
+  void remember_klass(Klass* k);
+  // Deal with a stack overflow condition
+  void handle_stack_overflow(HeapWord* lost);
+ private:
+  inline void do_yield_check();
+};
+
+// A parallel (MT) version of the above.
+// This closure is used during the concurrent marking phase
+// following the first checkpoint. Its use is buried in
+// the closure Par_MarkFromRootsClosure.
+class Par_PushOrMarkClosure: public OopClosure {
+  CMSCollector*    _collector;
+  MemRegion        _whole_span;
+  MemRegion        _span;        // local chunk
+  CMSBitMap*       _bit_map;
+  OopTaskQueue*    _work_queue;
+  CMSMarkStack*    _overflow_stack;
+  CMSMarkStack*    _revisit_stack;
+  HeapWord*  const _finger;
+  HeapWord** const _global_finger_addr;
+  Par_MarkFromRootsClosure* const _parent;
+  bool       const _should_remember_klasses;
+ public:
+  Par_PushOrMarkClosure(CMSCollector* cms_collector,
+                    MemRegion span,
+                    CMSBitMap* bit_map,
+                    OopTaskQueue* work_queue,
+                    CMSMarkStack*  mark_stack,
+                    CMSMarkStack*  revisit_stack,
+                    HeapWord*      finger,
+                    HeapWord**     global_finger_addr,
+                    Par_MarkFromRootsClosure* parent);
+  void do_oop(oop* p);
+  void do_oop_nv(oop* p)  { Par_PushOrMarkClosure::do_oop(p); }
+  const bool should_remember_klasses() const {
+    return _should_remember_klasses;
+  }
+  void remember_klass(Klass* k);
+  // Deal with a stack overflow condition
+  void handle_stack_overflow(HeapWord* lost);
+ private:
+  inline void do_yield_check();
+};
+
+// For objects in CMS generation, this closure marks
+// given objects (transitively) as being reachable/live.
+// This is currently used during the (weak) reference object
+// processing phase of the CMS final checkpoint step.
+class CMSKeepAliveClosure: public OopClosure {
+  CMSCollector* _collector;
+  MemRegion     _span;
+  CMSMarkStack* _mark_stack;
+  CMSBitMap*    _bit_map;
+ public:
+  CMSKeepAliveClosure(CMSCollector* collector, MemRegion span,
+                      CMSBitMap* bit_map, CMSMarkStack* mark_stack):
+    _collector(collector),
+    _span(span),
+    _bit_map(bit_map),
+    _mark_stack(mark_stack) { }
+
+  void do_oop(oop* p);
+  void do_oop_nv(oop* p) { CMSKeepAliveClosure::do_oop(p); }
+};
+
+class CMSInnerParMarkAndPushClosure: public OopClosure {
+  CMSCollector* _collector;
+  MemRegion     _span;
+  OopTaskQueue* _work_queue;
+  CMSBitMap*    _bit_map;
+ public:
+  CMSInnerParMarkAndPushClosure(CMSCollector* collector,
+                                MemRegion span, CMSBitMap* bit_map,
+                                OopTaskQueue* work_queue):
+    _collector(collector),
+    _span(span),
+    _bit_map(bit_map),
+    _work_queue(work_queue) { }
+  void do_oop(oop* p);
+  void do_oop_nv(oop* p) { CMSInnerParMarkAndPushClosure::do_oop(p); }
+};
+
+// A parallel (MT) version of the above, used when
+// reference processing is parallel; the only difference
+// is in the do_oop method.
+class CMSParKeepAliveClosure: public OopClosure {
+  CMSCollector* _collector;
+  MemRegion     _span;
+  OopTaskQueue* _work_queue;
+  CMSBitMap*    _bit_map;
+  CMSInnerParMarkAndPushClosure _mark_and_push;
+  const uint    _low_water_mark;
+  void trim_queue(uint max);
+ public:
+  CMSParKeepAliveClosure(CMSCollector* collector, MemRegion span,
+                         CMSBitMap* bit_map, OopTaskQueue* work_queue);
+  void do_oop(oop* p);
+  void do_oop_nv(oop* p) { CMSParKeepAliveClosure::do_oop(p); }
+};