duke@435: /* mikael@6198: * Copyright (c) 2007, 2013, Oracle and/or its affiliates. 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: * trims@1907: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA trims@1907: * or visit www.oracle.com if you need additional information or have any trims@1907: * questions. duke@435: * duke@435: */ duke@435: stefank@2314: #ifndef SHARE_VM_GC_IMPLEMENTATION_CONCURRENTMARKSWEEP_CMSOOPCLOSURES_HPP stefank@2314: #define SHARE_VM_GC_IMPLEMENTATION_CONCURRENTMARKSWEEP_CMSOOPCLOSURES_HPP stefank@2314: stefank@2314: #include "memory/genOopClosures.hpp" stefank@2314: 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: coleenp@4037: // Applies the given oop closure to all oops in all klasses visited. coleenp@4037: class CMKlassClosure : public KlassClosure { coleenp@4037: friend class CMSOopClosure; coleenp@4037: friend class CMSOopsInGenClosure; coleenp@4037: coleenp@4037: OopClosure* _oop_closure; coleenp@4037: coleenp@4037: // Used when _oop_closure couldn't be set in an initialization list. coleenp@4037: void initialize(OopClosure* oop_closure) { coleenp@4037: assert(_oop_closure == NULL, "Should only be called once"); coleenp@4037: _oop_closure = oop_closure; coleenp@4037: } coleenp@4037: public: coleenp@4037: CMKlassClosure(OopClosure* oop_closure = NULL) : _oop_closure(oop_closure) { } coleenp@4037: coleenp@4037: void do_klass(Klass* k); coleenp@4037: }; coleenp@4037: coleenp@4037: // The base class for all CMS marking closures. coleenp@4037: // It's used to proxy through the metadata to the oops defined in them. coleenp@4037: class CMSOopClosure: public ExtendedOopClosure { coleenp@4037: CMKlassClosure _klass_closure; coleenp@4037: public: coleenp@4037: CMSOopClosure() : ExtendedOopClosure() { coleenp@4037: _klass_closure.initialize(this); coleenp@4037: } coleenp@4037: CMSOopClosure(ReferenceProcessor* rp) : ExtendedOopClosure(rp) { coleenp@4037: _klass_closure.initialize(this); coleenp@4037: } coleenp@4037: coleenp@4037: virtual bool do_metadata() { return do_metadata_nv(); } coleenp@4037: inline bool do_metadata_nv() { return true; } coleenp@4037: coleenp@4037: virtual void do_klass(Klass* k); coleenp@4037: void do_klass_nv(Klass* k); coleenp@4037: coleenp@4037: virtual void do_class_loader_data(ClassLoaderData* cld); coleenp@4037: }; coleenp@4037: coleenp@4037: // TODO: This duplication of the CMSOopClosure class is only needed because coleenp@4037: // some CMS OopClosures derive from OopsInGenClosure. It would be good coleenp@4037: // to get rid of them completely. coleenp@4037: class CMSOopsInGenClosure: public OopsInGenClosure { coleenp@4037: CMKlassClosure _klass_closure; coleenp@4037: public: coleenp@4037: CMSOopsInGenClosure() { coleenp@4037: _klass_closure.initialize(this); coleenp@4037: } coleenp@4037: coleenp@4037: virtual bool do_metadata() { return do_metadata_nv(); } coleenp@4037: inline bool do_metadata_nv() { return true; } coleenp@4037: coleenp@4037: virtual void do_klass(Klass* k); coleenp@4037: void do_klass_nv(Klass* k); coleenp@4037: coleenp@4037: virtual void do_class_loader_data(ClassLoaderData* cld); coleenp@4037: }; coleenp@4037: coleenp@4037: class MarkRefsIntoClosure: public CMSOopsInGenClosure { coleenp@548: private: coleenp@548: const MemRegion _span; coleenp@548: CMSBitMap* _bitMap; coleenp@548: protected: coleenp@548: DO_OOP_WORK_DEFN duke@435: public: jrose@1429: MarkRefsIntoClosure(MemRegion span, CMSBitMap* bitMap); coleenp@548: virtual void do_oop(oop* p); coleenp@548: virtual void do_oop(narrowOop* p); coleenp@4037: duke@435: Prefetch::style prefetch_style() { duke@435: return Prefetch::do_read; duke@435: } duke@435: }; duke@435: jmasa@5461: class Par_MarkRefsIntoClosure: public CMSOopsInGenClosure { jmasa@5461: private: jmasa@5461: const MemRegion _span; jmasa@5461: CMSBitMap* _bitMap; jmasa@5461: protected: jmasa@5461: DO_OOP_WORK_DEFN jmasa@5461: public: jmasa@5461: Par_MarkRefsIntoClosure(MemRegion span, CMSBitMap* bitMap); jmasa@5461: virtual void do_oop(oop* p); jmasa@5461: virtual void do_oop(narrowOop* p); jmasa@5461: jmasa@5461: Prefetch::style prefetch_style() { jmasa@5461: return Prefetch::do_read; jmasa@5461: } jmasa@5461: }; jmasa@5461: duke@435: // A variant of the above used in certain kinds of CMS duke@435: // marking verification. coleenp@4037: class MarkRefsIntoVerifyClosure: public CMSOopsInGenClosure { coleenp@548: private: coleenp@548: const MemRegion _span; coleenp@548: CMSBitMap* _verification_bm; coleenp@548: CMSBitMap* _cms_bm; coleenp@548: protected: coleenp@548: DO_OOP_WORK_DEFN duke@435: public: duke@435: MarkRefsIntoVerifyClosure(MemRegion span, CMSBitMap* verification_bm, jrose@1429: CMSBitMap* cms_bm); coleenp@548: virtual void do_oop(oop* p); coleenp@548: virtual void do_oop(narrowOop* p); coleenp@4037: duke@435: Prefetch::style prefetch_style() { duke@435: return Prefetch::do_read; duke@435: } duke@435: }; duke@435: coleenp@4037: // The non-parallel version (the parallel version appears further below). coleenp@4037: class PushAndMarkClosure: public CMSOopClosure { coleenp@4037: private: jmasa@1370: CMSCollector* _collector; 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: 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); } coleenp@4037: duke@435: Prefetch::style prefetch_style() { duke@435: return Prefetch::do_read; duke@435: } duke@435: }; duke@435: coleenp@4037: // In the parallel case, 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. coleenp@4037: class Par_PushAndMarkClosure: public CMSOopClosure { coleenp@548: private: coleenp@4037: CMSCollector* _collector; 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, coleenp@4037: 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) { Par_PushAndMarkClosure::do_oop_work(p); } coleenp@548: inline void do_oop_nv(narrowOop* p) { Par_PushAndMarkClosure::do_oop_work(p); } coleenp@4037: duke@435: Prefetch::style prefetch_style() { duke@435: return Prefetch::do_read; duke@435: } duke@435: }; duke@435: duke@435: // The non-parallel version (the parallel version appears further below). coleenp@4037: class MarkRefsIntoAndScanClosure: public CMSOopsInGenClosure { 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, 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); } coleenp@4037: 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: } 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. coleenp@4037: class Par_MarkRefsIntoAndScanClosure: public CMSOopsInGenClosure { 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, coleenp@4037: 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) { Par_MarkRefsIntoAndScanClosure::do_oop_work(p); } coleenp@548: inline void do_oop_nv(narrowOop* p) { Par_MarkRefsIntoAndScanClosure::do_oop_work(p); } coleenp@4037: 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. coleenp@4037: class PushOrMarkClosure: public CMSOopClosure { coleenp@548: private: coleenp@4037: CMSCollector* _collector; 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: 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: 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. coleenp@4037: class Par_PushOrMarkClosure: public CMSOopClosure { coleenp@548: private: coleenp@4037: CMSCollector* _collector; 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: 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: 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. coleenp@4037: class CMSKeepAliveClosure: public CMSOopClosure { coleenp@548: private: coleenp@4037: CMSCollector* _collector; 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, coleenp@4037: 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: coleenp@4037: class CMSInnerParMarkAndPushClosure: public CMSOopClosure { coleenp@548: private: coleenp@4037: CMSCollector* _collector; 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: 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. coleenp@4037: class CMSParKeepAliveClosure: public CMSOopClosure { 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, coleenp@4037: CMSBitMap* bit_map, OopTaskQueue* work_queue); coleenp@548: virtual void do_oop(oop* p); coleenp@548: virtual void do_oop(narrowOop* p); duke@435: }; stefank@2314: stefank@2314: #endif // SHARE_VM_GC_IMPLEMENTATION_CONCURRENTMARKSWEEP_CMSOOPCLOSURES_HPP