--- /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); }
+};