duke@435: /* duke@435: * Copyright (c) 2007 Sun Microsystems, Inc. All Rights Reserved. duke@435: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. duke@435: * duke@435: * This code is free software; you can redistribute it and/or modify it duke@435: * under the terms of the GNU General Public License version 2 only, as duke@435: * published by the Free Software Foundation. duke@435: * duke@435: * This code is distributed in the hope that it will be useful, but WITHOUT duke@435: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or duke@435: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License duke@435: * version 2 for more details (a copy is included in the LICENSE file that duke@435: * accompanied this code). duke@435: * duke@435: * You should have received a copy of the GNU General Public License version duke@435: * 2 along with this work; if not, write to the Free Software Foundation, duke@435: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. duke@435: * duke@435: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, duke@435: * CA 95054 USA or visit www.sun.com if you need additional information or duke@435: * have any questions. duke@435: * duke@435: */ duke@435: duke@435: ///////////////////////////////////////////////////////////////// duke@435: // Closures used by ConcurrentMarkSweepGeneration's collector duke@435: ///////////////////////////////////////////////////////////////// duke@435: class ConcurrentMarkSweepGeneration; duke@435: class CMSBitMap; duke@435: class CMSMarkStack; duke@435: class CMSCollector; duke@435: class MarkFromRootsClosure; duke@435: class Par_MarkFromRootsClosure; duke@435: coleenp@548: // Decode the oop and call do_oop on it. coleenp@548: #define DO_OOP_WORK_DEFN \ coleenp@548: void do_oop(oop obj); \ coleenp@548: template inline void do_oop_work(T* p) { \ coleenp@548: T heap_oop = oopDesc::load_heap_oop(p); \ coleenp@548: if (!oopDesc::is_null(heap_oop)) { \ coleenp@548: oop obj = oopDesc::decode_heap_oop_not_null(heap_oop); \ coleenp@548: do_oop(obj); \ coleenp@548: } \ coleenp@548: } coleenp@548: duke@435: class MarkRefsIntoClosure: public OopsInGenClosure { coleenp@548: private: coleenp@548: const MemRegion _span; coleenp@548: CMSBitMap* _bitMap; coleenp@548: const bool _should_do_nmethods; coleenp@548: protected: coleenp@548: DO_OOP_WORK_DEFN duke@435: public: duke@435: MarkRefsIntoClosure(MemRegion span, CMSBitMap* bitMap, duke@435: bool should_do_nmethods); coleenp@548: virtual void do_oop(oop* p); coleenp@548: virtual void do_oop(narrowOop* p); coleenp@548: inline void do_oop_nv(oop* p) { MarkRefsIntoClosure::do_oop_work(p); } coleenp@548: inline void do_oop_nv(narrowOop* p) { MarkRefsIntoClosure::do_oop_work(p); } duke@435: bool do_header() { return true; } duke@435: virtual const bool do_nmethods() const { duke@435: return _should_do_nmethods; duke@435: } duke@435: Prefetch::style prefetch_style() { duke@435: return Prefetch::do_read; duke@435: } duke@435: }; duke@435: duke@435: // A variant of the above used in certain kinds of CMS duke@435: // marking verification. duke@435: class MarkRefsIntoVerifyClosure: public OopsInGenClosure { coleenp@548: private: coleenp@548: const MemRegion _span; coleenp@548: CMSBitMap* _verification_bm; coleenp@548: CMSBitMap* _cms_bm; coleenp@548: const bool _should_do_nmethods; coleenp@548: protected: coleenp@548: DO_OOP_WORK_DEFN duke@435: public: duke@435: MarkRefsIntoVerifyClosure(MemRegion span, CMSBitMap* verification_bm, duke@435: CMSBitMap* cms_bm, bool should_do_nmethods); coleenp@548: virtual void do_oop(oop* p); coleenp@548: virtual void do_oop(narrowOop* p); coleenp@548: inline void do_oop_nv(oop* p) { MarkRefsIntoVerifyClosure::do_oop_work(p); } coleenp@548: inline void do_oop_nv(narrowOop* p) { MarkRefsIntoVerifyClosure::do_oop_work(p); } duke@435: bool do_header() { return true; } duke@435: virtual const bool do_nmethods() const { duke@435: return _should_do_nmethods; duke@435: } duke@435: Prefetch::style prefetch_style() { duke@435: return Prefetch::do_read; duke@435: } duke@435: }; duke@435: jmasa@1370: // KlassRememberingOopClosure is used when marking of the permanent generation jmasa@1370: // is being done. It adds fields to support revisiting of klasses jmasa@1370: // for class unloading. _should_remember_klasses should be set to jmasa@1370: // indicate if klasses should be remembered. Currently that is whenever jmasa@1370: // CMS class unloading is turned on. The _revisit_stack is used jmasa@1370: // to save the klasses for later processing. jmasa@1370: class KlassRememberingOopClosure : public OopClosure { jmasa@1370: protected: jmasa@1370: CMSCollector* _collector; jmasa@1370: CMSMarkStack* _revisit_stack; jmasa@1370: bool const _should_remember_klasses; jmasa@1370: public: jmasa@1370: void check_remember_klasses() const PRODUCT_RETURN; jmasa@1370: virtual const bool should_remember_klasses() const { jmasa@1370: check_remember_klasses(); jmasa@1370: return _should_remember_klasses; jmasa@1370: } jmasa@1370: virtual void remember_klass(Klass* k); jmasa@1370: jmasa@1370: KlassRememberingOopClosure(CMSCollector* collector, jmasa@1370: ReferenceProcessor* rp, jmasa@1370: CMSMarkStack* revisit_stack); jmasa@1370: }; jmasa@1370: jmasa@1370: // Similar to KlassRememberingOopClosure for use when multiple jmasa@1370: // GC threads will execute the closure. jmasa@1370: jmasa@1370: class Par_KlassRememberingOopClosure : public KlassRememberingOopClosure { jmasa@1370: public: jmasa@1370: Par_KlassRememberingOopClosure(CMSCollector* collector, jmasa@1370: ReferenceProcessor* rp, jmasa@1370: CMSMarkStack* revisit_stack): jmasa@1370: KlassRememberingOopClosure(collector, rp, revisit_stack) {} jmasa@1370: virtual void remember_klass(Klass* k); jmasa@1370: }; jmasa@1370: duke@435: // The non-parallel version (the parallel version appears further below). jmasa@1370: class PushAndMarkClosure: public KlassRememberingOopClosure { coleenp@548: private: coleenp@548: MemRegion _span; coleenp@548: CMSBitMap* _bit_map; coleenp@548: CMSBitMap* _mod_union_table; coleenp@548: CMSMarkStack* _mark_stack; coleenp@548: bool _concurrent_precleaning; coleenp@548: protected: coleenp@548: DO_OOP_WORK_DEFN duke@435: public: duke@435: PushAndMarkClosure(CMSCollector* collector, duke@435: MemRegion span, duke@435: ReferenceProcessor* rp, duke@435: CMSBitMap* bit_map, duke@435: CMSBitMap* mod_union_table, coleenp@548: CMSMarkStack* mark_stack, coleenp@548: CMSMarkStack* revisit_stack, coleenp@548: bool concurrent_precleaning); coleenp@548: virtual void do_oop(oop* p); coleenp@548: virtual void do_oop(narrowOop* p); coleenp@548: inline void do_oop_nv(oop* p) { PushAndMarkClosure::do_oop_work(p); } coleenp@548: inline void do_oop_nv(narrowOop* p) { PushAndMarkClosure::do_oop_work(p); } duke@435: bool do_header() { return true; } duke@435: Prefetch::style prefetch_style() { duke@435: return Prefetch::do_read; duke@435: } ysr@1376: // In support of class unloading ysr@1376: virtual const bool should_remember_mdo() const { ysr@1376: return false; ysr@1376: // return _should_remember_klasses; ysr@1376: } ysr@1376: virtual void remember_mdo(DataLayout* v); duke@435: }; duke@435: duke@435: // In the parallel case, the revisit stack, the bit map and the duke@435: // reference processor are currently all shared. Access to duke@435: // these shared mutable structures must use appropriate duke@435: // synchronization (for instance, via CAS). The marking stack duke@435: // used in the non-parallel case above is here replaced with duke@435: // an OopTaskQueue structure to allow efficient work stealing. jmasa@1370: class Par_PushAndMarkClosure: public Par_KlassRememberingOopClosure { coleenp@548: private: coleenp@548: MemRegion _span; coleenp@548: CMSBitMap* _bit_map; coleenp@548: OopTaskQueue* _work_queue; coleenp@548: protected: coleenp@548: DO_OOP_WORK_DEFN duke@435: public: duke@435: Par_PushAndMarkClosure(CMSCollector* collector, duke@435: MemRegion span, duke@435: ReferenceProcessor* rp, duke@435: CMSBitMap* bit_map, duke@435: OopTaskQueue* work_queue, duke@435: CMSMarkStack* revisit_stack); coleenp@548: virtual void do_oop(oop* p); coleenp@548: virtual void do_oop(narrowOop* p); coleenp@548: inline void do_oop_nv(oop* p) { Par_PushAndMarkClosure::do_oop_work(p); } coleenp@548: inline void do_oop_nv(narrowOop* p) { Par_PushAndMarkClosure::do_oop_work(p); } duke@435: bool do_header() { return true; } duke@435: Prefetch::style prefetch_style() { duke@435: return Prefetch::do_read; duke@435: } ysr@1376: // In support of class unloading ysr@1376: virtual const bool should_remember_mdo() const { ysr@1376: return false; ysr@1376: // return _should_remember_klasses; ysr@1376: } ysr@1376: virtual void remember_mdo(DataLayout* v); duke@435: }; duke@435: duke@435: // The non-parallel version (the parallel version appears further below). duke@435: class MarkRefsIntoAndScanClosure: public OopsInGenClosure { coleenp@548: private: coleenp@548: MemRegion _span; coleenp@548: CMSBitMap* _bit_map; coleenp@548: CMSMarkStack* _mark_stack; coleenp@548: PushAndMarkClosure _pushAndMarkClosure; coleenp@548: CMSCollector* _collector; coleenp@548: Mutex* _freelistLock; coleenp@548: bool _yield; duke@435: // Whether closure is being used for concurrent precleaning coleenp@548: bool _concurrent_precleaning; coleenp@548: protected: coleenp@548: DO_OOP_WORK_DEFN duke@435: public: duke@435: MarkRefsIntoAndScanClosure(MemRegion span, duke@435: ReferenceProcessor* rp, duke@435: CMSBitMap* bit_map, duke@435: CMSBitMap* mod_union_table, coleenp@548: CMSMarkStack* mark_stack, coleenp@548: CMSMarkStack* revisit_stack, duke@435: CMSCollector* collector, duke@435: bool should_yield, duke@435: bool concurrent_precleaning); coleenp@548: virtual void do_oop(oop* p); coleenp@548: virtual void do_oop(narrowOop* p); coleenp@548: inline void do_oop_nv(oop* p) { MarkRefsIntoAndScanClosure::do_oop_work(p); } coleenp@548: inline void do_oop_nv(narrowOop* p) { MarkRefsIntoAndScanClosure::do_oop_work(p); } duke@435: bool do_header() { return true; } duke@435: virtual const bool do_nmethods() const { return true; } duke@435: Prefetch::style prefetch_style() { duke@435: return Prefetch::do_read; duke@435: } duke@435: void set_freelistLock(Mutex* m) { duke@435: _freelistLock = m; duke@435: } jmasa@1370: virtual const bool should_remember_klasses() const { jmasa@1370: return _pushAndMarkClosure.should_remember_klasses(); jmasa@1370: } jmasa@1370: virtual void remember_klass(Klass* k) { jmasa@1370: _pushAndMarkClosure.remember_klass(k); jmasa@1370: } duke@435: duke@435: private: duke@435: inline void do_yield_check(); duke@435: void do_yield_work(); duke@435: bool take_from_overflow_list(); duke@435: }; duke@435: duke@435: // Tn this, the parallel avatar of MarkRefsIntoAndScanClosure, the revisit duke@435: // stack and the bitMap are shared, so access needs to be suitably duke@435: // sycnhronized. An OopTaskQueue structure, supporting efficient duke@435: // workstealing, replaces a CMSMarkStack for storing grey objects. duke@435: class Par_MarkRefsIntoAndScanClosure: public OopsInGenClosure { coleenp@548: private: coleenp@548: MemRegion _span; coleenp@548: CMSBitMap* _bit_map; coleenp@548: OopTaskQueue* _work_queue; coleenp@548: const uint _low_water_mark; coleenp@548: Par_PushAndMarkClosure _par_pushAndMarkClosure; coleenp@548: protected: coleenp@548: DO_OOP_WORK_DEFN duke@435: public: duke@435: Par_MarkRefsIntoAndScanClosure(CMSCollector* collector, duke@435: MemRegion span, duke@435: ReferenceProcessor* rp, duke@435: CMSBitMap* bit_map, duke@435: OopTaskQueue* work_queue, duke@435: CMSMarkStack* revisit_stack); coleenp@548: virtual void do_oop(oop* p); coleenp@548: virtual void do_oop(narrowOop* p); coleenp@548: inline void do_oop_nv(oop* p) { Par_MarkRefsIntoAndScanClosure::do_oop_work(p); } coleenp@548: inline void do_oop_nv(narrowOop* p) { Par_MarkRefsIntoAndScanClosure::do_oop_work(p); } duke@435: bool do_header() { return true; } duke@435: virtual const bool do_nmethods() const { return true; } jmasa@1370: // When ScanMarkedObjectsAgainClosure is used, jmasa@1370: // it passes [Par_]MarkRefsIntoAndScanClosure to oop_oop_iterate(), jmasa@1370: // and this delegation is used. jmasa@1370: virtual const bool should_remember_klasses() const { jmasa@1370: return _par_pushAndMarkClosure.should_remember_klasses(); jmasa@1370: } jmasa@1370: // See comment on should_remember_klasses() above. jmasa@1370: virtual void remember_klass(Klass* k) { jmasa@1370: _par_pushAndMarkClosure.remember_klass(k); jmasa@1370: } duke@435: Prefetch::style prefetch_style() { duke@435: return Prefetch::do_read; duke@435: } duke@435: void trim_queue(uint size); duke@435: }; duke@435: duke@435: // This closure is used during the concurrent marking phase duke@435: // following the first checkpoint. Its use is buried in duke@435: // the closure MarkFromRootsClosure. jmasa@1370: class PushOrMarkClosure: public KlassRememberingOopClosure { coleenp@548: private: coleenp@548: MemRegion _span; coleenp@548: CMSBitMap* _bitMap; coleenp@548: CMSMarkStack* _markStack; coleenp@548: HeapWord* const _finger; coleenp@548: MarkFromRootsClosure* const coleenp@548: _parent; coleenp@548: protected: coleenp@548: DO_OOP_WORK_DEFN duke@435: public: duke@435: PushOrMarkClosure(CMSCollector* cms_collector, duke@435: MemRegion span, duke@435: CMSBitMap* bitMap, coleenp@548: CMSMarkStack* markStack, coleenp@548: CMSMarkStack* revisitStack, coleenp@548: HeapWord* finger, duke@435: MarkFromRootsClosure* parent); coleenp@548: virtual void do_oop(oop* p); coleenp@548: virtual void do_oop(narrowOop* p); coleenp@548: inline void do_oop_nv(oop* p) { PushOrMarkClosure::do_oop_work(p); } coleenp@548: inline void do_oop_nv(narrowOop* p) { PushOrMarkClosure::do_oop_work(p); } ysr@1376: // In support of class unloading ysr@1376: virtual const bool should_remember_mdo() const { ysr@1376: return false; ysr@1376: // return _should_remember_klasses; ysr@1376: } ysr@1376: virtual void remember_mdo(DataLayout* v); ysr@1376: duke@435: // Deal with a stack overflow condition duke@435: void handle_stack_overflow(HeapWord* lost); duke@435: private: duke@435: inline void do_yield_check(); duke@435: }; duke@435: duke@435: // A parallel (MT) version of the above. duke@435: // This closure is used during the concurrent marking phase duke@435: // following the first checkpoint. Its use is buried in duke@435: // the closure Par_MarkFromRootsClosure. jmasa@1370: class Par_PushOrMarkClosure: public Par_KlassRememberingOopClosure { coleenp@548: private: duke@435: MemRegion _whole_span; duke@435: MemRegion _span; // local chunk duke@435: CMSBitMap* _bit_map; duke@435: OopTaskQueue* _work_queue; duke@435: CMSMarkStack* _overflow_stack; duke@435: HeapWord* const _finger; duke@435: HeapWord** const _global_finger_addr; coleenp@548: Par_MarkFromRootsClosure* const coleenp@548: _parent; coleenp@548: protected: coleenp@548: DO_OOP_WORK_DEFN duke@435: public: duke@435: Par_PushOrMarkClosure(CMSCollector* cms_collector, coleenp@548: MemRegion span, coleenp@548: CMSBitMap* bit_map, coleenp@548: OopTaskQueue* work_queue, coleenp@548: CMSMarkStack* mark_stack, coleenp@548: CMSMarkStack* revisit_stack, coleenp@548: HeapWord* finger, coleenp@548: HeapWord** global_finger_addr, coleenp@548: Par_MarkFromRootsClosure* parent); coleenp@548: virtual void do_oop(oop* p); coleenp@548: virtual void do_oop(narrowOop* p); coleenp@548: inline void do_oop_nv(oop* p) { Par_PushOrMarkClosure::do_oop_work(p); } coleenp@548: inline void do_oop_nv(narrowOop* p) { Par_PushOrMarkClosure::do_oop_work(p); } ysr@1376: // In support of class unloading ysr@1376: virtual const bool should_remember_mdo() const { ysr@1376: return false; ysr@1376: // return _should_remember_klasses; ysr@1376: } ysr@1376: virtual void remember_mdo(DataLayout* v); ysr@1376: duke@435: // Deal with a stack overflow condition duke@435: void handle_stack_overflow(HeapWord* lost); duke@435: private: duke@435: inline void do_yield_check(); duke@435: }; duke@435: duke@435: // For objects in CMS generation, this closure marks duke@435: // given objects (transitively) as being reachable/live. duke@435: // This is currently used during the (weak) reference object ysr@887: // processing phase of the CMS final checkpoint step, as ysr@887: // well as during the concurrent precleaning of the discovered ysr@887: // reference lists. jmasa@1370: class CMSKeepAliveClosure: public KlassRememberingOopClosure { coleenp@548: private: ysr@578: const MemRegion _span; duke@435: CMSMarkStack* _mark_stack; duke@435: CMSBitMap* _bit_map; ysr@887: bool _concurrent_precleaning; coleenp@548: protected: coleenp@548: DO_OOP_WORK_DEFN duke@435: public: duke@435: CMSKeepAliveClosure(CMSCollector* collector, MemRegion span, ysr@887: CMSBitMap* bit_map, CMSMarkStack* mark_stack, jmasa@1370: CMSMarkStack* revisit_stack, bool cpc); ysr@887: bool concurrent_precleaning() const { return _concurrent_precleaning; } coleenp@548: virtual void do_oop(oop* p); coleenp@548: virtual void do_oop(narrowOop* p); coleenp@548: inline void do_oop_nv(oop* p) { CMSKeepAliveClosure::do_oop_work(p); } coleenp@548: inline void do_oop_nv(narrowOop* p) { CMSKeepAliveClosure::do_oop_work(p); } duke@435: }; duke@435: jmasa@1370: class CMSInnerParMarkAndPushClosure: public Par_KlassRememberingOopClosure { coleenp@548: private: duke@435: MemRegion _span; duke@435: OopTaskQueue* _work_queue; duke@435: CMSBitMap* _bit_map; coleenp@548: protected: coleenp@548: DO_OOP_WORK_DEFN duke@435: public: duke@435: CMSInnerParMarkAndPushClosure(CMSCollector* collector, duke@435: MemRegion span, CMSBitMap* bit_map, jmasa@1370: CMSMarkStack* revisit_stack, jmasa@1370: OopTaskQueue* work_queue); coleenp@548: virtual void do_oop(oop* p); coleenp@548: virtual void do_oop(narrowOop* p); coleenp@548: inline void do_oop_nv(oop* p) { CMSInnerParMarkAndPushClosure::do_oop_work(p); } coleenp@548: inline void do_oop_nv(narrowOop* p) { CMSInnerParMarkAndPushClosure::do_oop_work(p); } duke@435: }; duke@435: duke@435: // A parallel (MT) version of the above, used when duke@435: // reference processing is parallel; the only difference duke@435: // is in the do_oop method. jmasa@1370: class CMSParKeepAliveClosure: public Par_KlassRememberingOopClosure { coleenp@548: private: duke@435: MemRegion _span; duke@435: OopTaskQueue* _work_queue; duke@435: CMSBitMap* _bit_map; coleenp@548: CMSInnerParMarkAndPushClosure coleenp@548: _mark_and_push; duke@435: const uint _low_water_mark; duke@435: void trim_queue(uint max); coleenp@548: protected: coleenp@548: DO_OOP_WORK_DEFN duke@435: public: duke@435: CMSParKeepAliveClosure(CMSCollector* collector, MemRegion span, jmasa@1370: CMSBitMap* bit_map, CMSMarkStack* revisit_stack, jmasa@1370: OopTaskQueue* work_queue); coleenp@548: virtual void do_oop(oop* p); coleenp@548: virtual void do_oop(narrowOop* p); coleenp@548: inline void do_oop_nv(oop* p) { CMSParKeepAliveClosure::do_oop_work(p); } coleenp@548: inline void do_oop_nv(narrowOop* p) { CMSParKeepAliveClosure::do_oop_work(p); } duke@435: };