hotspot/src/share/vm/gc/cms/cmsOopClosures.hpp
changeset 30764 fec48bf5a827
parent 25356 4a4a482298a6
child 30878 f1702744b3a4
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/gc/cms/cmsOopClosures.hpp	Wed May 13 15:16:06 2015 +0200
@@ -0,0 +1,362 @@
+/*
+ * Copyright (c) 2007, 2015, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef SHARE_VM_GC_CMS_CMSOOPCLOSURES_HPP
+#define SHARE_VM_GC_CMS_CMSOOPCLOSURES_HPP
+
+#include "gc/shared/genOopClosures.hpp"
+#include "memory/iterator.hpp"
+
+/////////////////////////////////////////////////////////////////
+// Closures used by ConcurrentMarkSweepGeneration's collector
+/////////////////////////////////////////////////////////////////
+class ConcurrentMarkSweepGeneration;
+class CMSBitMap;
+class CMSMarkStack;
+class CMSCollector;
+class MarkFromRootsClosure;
+class Par_MarkFromRootsClosure;
+
+// Decode the oop and call do_oop on it.
+#define DO_OOP_WORK_DEFN \
+  void do_oop(oop obj);                                   \
+  template <class T> inline void do_oop_work(T* p) {      \
+    T heap_oop = oopDesc::load_heap_oop(p);               \
+    if (!oopDesc::is_null(heap_oop)) {                    \
+      oop obj = oopDesc::decode_heap_oop_not_null(heap_oop);       \
+      do_oop(obj);                                        \
+    }                                                     \
+  }
+
+// TODO: This duplication of the MetadataAwareOopClosure class is only needed
+//       because some CMS OopClosures derive from OopsInGenClosure. It would be
+//       good to get rid of them completely.
+class MetadataAwareOopsInGenClosure: public OopsInGenClosure {
+  KlassToOopClosure _klass_closure;
+ public:
+  MetadataAwareOopsInGenClosure() {
+    _klass_closure.initialize(this);
+  }
+
+  virtual bool do_metadata()    { return do_metadata_nv(); }
+  inline  bool do_metadata_nv() { return true; }
+
+  virtual void do_klass(Klass* k);
+  void do_klass_nv(Klass* k);
+
+  virtual void do_class_loader_data(ClassLoaderData* cld);
+};
+
+class MarkRefsIntoClosure: public MetadataAwareOopsInGenClosure {
+ private:
+  const MemRegion _span;
+  CMSBitMap*      _bitMap;
+ protected:
+  DO_OOP_WORK_DEFN
+ public:
+  MarkRefsIntoClosure(MemRegion span, CMSBitMap* bitMap);
+  virtual void do_oop(oop* p);
+  virtual void do_oop(narrowOop* p);
+};
+
+class Par_MarkRefsIntoClosure: public MetadataAwareOopsInGenClosure {
+ private:
+  const MemRegion _span;
+  CMSBitMap*      _bitMap;
+ protected:
+  DO_OOP_WORK_DEFN
+ public:
+  Par_MarkRefsIntoClosure(MemRegion span, CMSBitMap* bitMap);
+  virtual void do_oop(oop* p);
+  virtual void do_oop(narrowOop* p);
+};
+
+// A variant of the above used in certain kinds of CMS
+// marking verification.
+class MarkRefsIntoVerifyClosure: public MetadataAwareOopsInGenClosure {
+ private:
+  const MemRegion _span;
+  CMSBitMap*      _verification_bm;
+  CMSBitMap*      _cms_bm;
+ protected:
+  DO_OOP_WORK_DEFN
+ public:
+  MarkRefsIntoVerifyClosure(MemRegion span, CMSBitMap* verification_bm,
+                            CMSBitMap* cms_bm);
+  virtual void do_oop(oop* p);
+  virtual void do_oop(narrowOop* p);
+};
+
+// The non-parallel version (the parallel version appears further below).
+class PushAndMarkClosure: public MetadataAwareOopClosure {
+ private:
+  CMSCollector* _collector;
+  MemRegion     _span;
+  CMSBitMap*    _bit_map;
+  CMSBitMap*    _mod_union_table;
+  CMSMarkStack* _mark_stack;
+  bool          _concurrent_precleaning;
+ protected:
+  DO_OOP_WORK_DEFN
+ public:
+  PushAndMarkClosure(CMSCollector* collector,
+                     MemRegion span,
+                     ReferenceProcessor* rp,
+                     CMSBitMap* bit_map,
+                     CMSBitMap* mod_union_table,
+                     CMSMarkStack* mark_stack,
+                     bool concurrent_precleaning);
+  virtual void do_oop(oop* p);
+  virtual void do_oop(narrowOop* p);
+  inline void do_oop_nv(oop* p)       { PushAndMarkClosure::do_oop_work(p); }
+  inline void do_oop_nv(narrowOop* p) { PushAndMarkClosure::do_oop_work(p); }
+};
+
+// In the parallel case, 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 MetadataAwareOopClosure {
+ private:
+  CMSCollector* _collector;
+  MemRegion     _span;
+  CMSBitMap*    _bit_map;
+  OopTaskQueue* _work_queue;
+ protected:
+  DO_OOP_WORK_DEFN
+ public:
+  Par_PushAndMarkClosure(CMSCollector* collector,
+                         MemRegion span,
+                         ReferenceProcessor* rp,
+                         CMSBitMap* bit_map,
+                         OopTaskQueue* work_queue);
+  virtual void do_oop(oop* p);
+  virtual void do_oop(narrowOop* p);
+  inline void do_oop_nv(oop* p)       { Par_PushAndMarkClosure::do_oop_work(p); }
+  inline void do_oop_nv(narrowOop* p) { Par_PushAndMarkClosure::do_oop_work(p); }
+};
+
+// The non-parallel version (the parallel version appears further below).
+class MarkRefsIntoAndScanClosure: public MetadataAwareOopsInGenClosure {
+ private:
+  MemRegion          _span;
+  CMSBitMap*         _bit_map;
+  CMSMarkStack*      _mark_stack;
+  PushAndMarkClosure _pushAndMarkClosure;
+  CMSCollector*      _collector;
+  Mutex*             _freelistLock;
+  bool               _yield;
+  // Whether closure is being used for concurrent precleaning
+  bool               _concurrent_precleaning;
+ protected:
+  DO_OOP_WORK_DEFN
+ public:
+  MarkRefsIntoAndScanClosure(MemRegion span,
+                             ReferenceProcessor* rp,
+                             CMSBitMap* bit_map,
+                             CMSBitMap* mod_union_table,
+                             CMSMarkStack* mark_stack,
+                             CMSCollector* collector,
+                             bool should_yield,
+                             bool concurrent_precleaning);
+  virtual void do_oop(oop* p);
+  virtual void do_oop(narrowOop* p);
+  inline void do_oop_nv(oop* p)       { MarkRefsIntoAndScanClosure::do_oop_work(p); }
+  inline void do_oop_nv(narrowOop* p) { MarkRefsIntoAndScanClosure::do_oop_work(p); }
+
+  void set_freelistLock(Mutex* m) {
+    _freelistLock = m;
+  }
+
+ private:
+  inline void do_yield_check();
+  void do_yield_work();
+  bool take_from_overflow_list();
+};
+
+// In this, the parallel avatar of MarkRefsIntoAndScanClosure, the revisit
+// stack and the bitMap are shared, so access needs to be suitably
+// synchronized. An OopTaskQueue structure, supporting efficient
+// work stealing, replaces a CMSMarkStack for storing grey objects.
+class Par_MarkRefsIntoAndScanClosure: public MetadataAwareOopsInGenClosure {
+ private:
+  MemRegion              _span;
+  CMSBitMap*             _bit_map;
+  OopTaskQueue*          _work_queue;
+  const uint             _low_water_mark;
+  Par_PushAndMarkClosure _par_pushAndMarkClosure;
+ protected:
+  DO_OOP_WORK_DEFN
+ public:
+  Par_MarkRefsIntoAndScanClosure(CMSCollector* collector,
+                                 MemRegion span,
+                                 ReferenceProcessor* rp,
+                                 CMSBitMap* bit_map,
+                                 OopTaskQueue* work_queue);
+  virtual void do_oop(oop* p);
+  virtual void do_oop(narrowOop* p);
+  inline void do_oop_nv(oop* p)       { Par_MarkRefsIntoAndScanClosure::do_oop_work(p); }
+  inline void do_oop_nv(narrowOop* p) { Par_MarkRefsIntoAndScanClosure::do_oop_work(p); }
+
+  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 MetadataAwareOopClosure {
+ private:
+  CMSCollector*   _collector;
+  MemRegion       _span;
+  CMSBitMap*      _bitMap;
+  CMSMarkStack*   _markStack;
+  HeapWord* const _finger;
+  MarkFromRootsClosure* const
+                  _parent;
+ protected:
+  DO_OOP_WORK_DEFN
+ public:
+  PushOrMarkClosure(CMSCollector* cms_collector,
+                    MemRegion span,
+                    CMSBitMap* bitMap,
+                    CMSMarkStack* markStack,
+                    HeapWord* finger,
+                    MarkFromRootsClosure* parent);
+  virtual void do_oop(oop* p);
+  virtual void do_oop(narrowOop* p);
+  inline void do_oop_nv(oop* p)       { PushOrMarkClosure::do_oop_work(p); }
+  inline void do_oop_nv(narrowOop* p) { PushOrMarkClosure::do_oop_work(p); }
+
+  // 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 MetadataAwareOopClosure {
+ private:
+  CMSCollector*    _collector;
+  MemRegion        _whole_span;
+  MemRegion        _span;        // local chunk
+  CMSBitMap*       _bit_map;
+  OopTaskQueue*    _work_queue;
+  CMSMarkStack*    _overflow_stack;
+  HeapWord*  const _finger;
+  HeapWord** const _global_finger_addr;
+  Par_MarkFromRootsClosure* const
+                   _parent;
+ protected:
+  DO_OOP_WORK_DEFN
+ public:
+  Par_PushOrMarkClosure(CMSCollector* cms_collector,
+                        MemRegion span,
+                        CMSBitMap* bit_map,
+                        OopTaskQueue* work_queue,
+                        CMSMarkStack* mark_stack,
+                        HeapWord* finger,
+                        HeapWord** global_finger_addr,
+                        Par_MarkFromRootsClosure* parent);
+  virtual void do_oop(oop* p);
+  virtual void do_oop(narrowOop* p);
+  inline void do_oop_nv(oop* p)       { Par_PushOrMarkClosure::do_oop_work(p); }
+  inline void do_oop_nv(narrowOop* p) { Par_PushOrMarkClosure::do_oop_work(p); }
+
+  // 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, as
+// well as during the concurrent precleaning of the discovered
+// reference lists.
+class CMSKeepAliveClosure: public MetadataAwareOopClosure {
+ private:
+  CMSCollector* _collector;
+  const MemRegion _span;
+  CMSMarkStack* _mark_stack;
+  CMSBitMap*    _bit_map;
+  bool          _concurrent_precleaning;
+ protected:
+  DO_OOP_WORK_DEFN
+ public:
+  CMSKeepAliveClosure(CMSCollector* collector, MemRegion span,
+                      CMSBitMap* bit_map, CMSMarkStack* mark_stack,
+                      bool cpc);
+  bool    concurrent_precleaning() const { return _concurrent_precleaning; }
+  virtual void do_oop(oop* p);
+  virtual void do_oop(narrowOop* p);
+  inline void do_oop_nv(oop* p)       { CMSKeepAliveClosure::do_oop_work(p); }
+  inline void do_oop_nv(narrowOop* p) { CMSKeepAliveClosure::do_oop_work(p); }
+};
+
+class CMSInnerParMarkAndPushClosure: public MetadataAwareOopClosure {
+ private:
+  CMSCollector* _collector;
+  MemRegion     _span;
+  OopTaskQueue* _work_queue;
+  CMSBitMap*    _bit_map;
+ protected:
+  DO_OOP_WORK_DEFN
+ public:
+  CMSInnerParMarkAndPushClosure(CMSCollector* collector,
+                                MemRegion span, CMSBitMap* bit_map,
+                                OopTaskQueue* work_queue);
+  virtual void do_oop(oop* p);
+  virtual void do_oop(narrowOop* p);
+  inline void do_oop_nv(oop* p)       { CMSInnerParMarkAndPushClosure::do_oop_work(p); }
+  inline void do_oop_nv(narrowOop* p) { CMSInnerParMarkAndPushClosure::do_oop_work(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 MetadataAwareOopClosure {
+ private:
+  MemRegion     _span;
+  OopTaskQueue* _work_queue;
+  CMSBitMap*    _bit_map;
+  CMSInnerParMarkAndPushClosure
+                _mark_and_push;
+  const uint    _low_water_mark;
+  void trim_queue(uint max);
+ protected:
+  DO_OOP_WORK_DEFN
+ public:
+  CMSParKeepAliveClosure(CMSCollector* collector, MemRegion span,
+                         CMSBitMap* bit_map, OopTaskQueue* work_queue);
+  virtual void do_oop(oop* p);
+  virtual void do_oop(narrowOop* p);
+};
+
+#endif // SHARE_VM_GC_CMS_CMSOOPCLOSURES_HPP