aoqi@0: /* aoqi@0: * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved. aoqi@0: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. aoqi@0: * aoqi@0: * This code is free software; you can redistribute it and/or modify it aoqi@0: * under the terms of the GNU General Public License version 2 only, as aoqi@0: * published by the Free Software Foundation. aoqi@0: * aoqi@0: * This code is distributed in the hope that it will be useful, but WITHOUT aoqi@0: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or aoqi@0: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License aoqi@0: * version 2 for more details (a copy is included in the LICENSE file that aoqi@0: * accompanied this code). aoqi@0: * aoqi@0: * You should have received a copy of the GNU General Public License version aoqi@0: * 2 along with this work; if not, write to the Free Software Foundation, aoqi@0: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. aoqi@0: * aoqi@0: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA aoqi@0: * or visit www.oracle.com if you need additional information or have any aoqi@0: * questions. aoqi@0: * aoqi@0: */ aoqi@0: aoqi@0: #ifndef SHARE_VM_GC_IMPLEMENTATION_CONCURRENTMARKSWEEP_CMSOOPCLOSURES_HPP aoqi@0: #define SHARE_VM_GC_IMPLEMENTATION_CONCURRENTMARKSWEEP_CMSOOPCLOSURES_HPP aoqi@0: aoqi@0: #include "memory/genOopClosures.hpp" aoqi@0: aoqi@0: ///////////////////////////////////////////////////////////////// aoqi@0: // Closures used by ConcurrentMarkSweepGeneration's collector aoqi@0: ///////////////////////////////////////////////////////////////// aoqi@0: class ConcurrentMarkSweepGeneration; aoqi@0: class CMSBitMap; aoqi@0: class CMSMarkStack; aoqi@0: class CMSCollector; aoqi@0: class MarkFromRootsClosure; aoqi@0: class Par_MarkFromRootsClosure; aoqi@0: aoqi@0: // Decode the oop and call do_oop on it. aoqi@0: #define DO_OOP_WORK_DEFN \ aoqi@0: void do_oop(oop obj); \ aoqi@0: template inline void do_oop_work(T* p) { \ aoqi@0: T heap_oop = oopDesc::load_heap_oop(p); \ aoqi@0: if (!oopDesc::is_null(heap_oop)) { \ aoqi@0: oop obj = oopDesc::decode_heap_oop_not_null(heap_oop); \ aoqi@0: do_oop(obj); \ aoqi@0: } \ aoqi@0: } aoqi@0: aoqi@0: // Applies the given oop closure to all oops in all klasses visited. aoqi@0: class CMKlassClosure : public KlassClosure { aoqi@0: friend class CMSOopClosure; aoqi@0: friend class CMSOopsInGenClosure; aoqi@0: aoqi@0: OopClosure* _oop_closure; aoqi@0: aoqi@0: // Used when _oop_closure couldn't be set in an initialization list. aoqi@0: void initialize(OopClosure* oop_closure) { aoqi@0: assert(_oop_closure == NULL, "Should only be called once"); aoqi@0: _oop_closure = oop_closure; aoqi@0: } aoqi@0: public: aoqi@0: CMKlassClosure(OopClosure* oop_closure = NULL) : _oop_closure(oop_closure) { } aoqi@0: aoqi@0: void do_klass(Klass* k); aoqi@0: }; aoqi@0: aoqi@0: // The base class for all CMS marking closures. aoqi@0: // It's used to proxy through the metadata to the oops defined in them. aoqi@0: class CMSOopClosure: public ExtendedOopClosure { aoqi@0: CMKlassClosure _klass_closure; aoqi@0: public: aoqi@0: CMSOopClosure() : ExtendedOopClosure() { aoqi@0: _klass_closure.initialize(this); aoqi@0: } aoqi@0: CMSOopClosure(ReferenceProcessor* rp) : ExtendedOopClosure(rp) { aoqi@0: _klass_closure.initialize(this); aoqi@0: } aoqi@0: aoqi@0: virtual bool do_metadata() { return do_metadata_nv(); } aoqi@0: inline bool do_metadata_nv() { return true; } aoqi@0: aoqi@0: virtual void do_klass(Klass* k); aoqi@0: void do_klass_nv(Klass* k); aoqi@0: aoqi@0: virtual void do_class_loader_data(ClassLoaderData* cld); aoqi@0: }; aoqi@0: aoqi@0: // TODO: This duplication of the CMSOopClosure class is only needed because aoqi@0: // some CMS OopClosures derive from OopsInGenClosure. It would be good aoqi@0: // to get rid of them completely. aoqi@0: class CMSOopsInGenClosure: public OopsInGenClosure { aoqi@0: CMKlassClosure _klass_closure; aoqi@0: public: aoqi@0: CMSOopsInGenClosure() { aoqi@0: _klass_closure.initialize(this); aoqi@0: } aoqi@0: aoqi@0: virtual bool do_metadata() { return do_metadata_nv(); } aoqi@0: inline bool do_metadata_nv() { return true; } aoqi@0: aoqi@0: virtual void do_klass(Klass* k); aoqi@0: void do_klass_nv(Klass* k); aoqi@0: aoqi@0: virtual void do_class_loader_data(ClassLoaderData* cld); aoqi@0: }; aoqi@0: aoqi@0: class MarkRefsIntoClosure: public CMSOopsInGenClosure { aoqi@0: private: aoqi@0: const MemRegion _span; aoqi@0: CMSBitMap* _bitMap; aoqi@0: protected: aoqi@0: DO_OOP_WORK_DEFN aoqi@0: public: aoqi@0: MarkRefsIntoClosure(MemRegion span, CMSBitMap* bitMap); aoqi@0: virtual void do_oop(oop* p); aoqi@0: virtual void do_oop(narrowOop* p); aoqi@0: aoqi@0: Prefetch::style prefetch_style() { aoqi@0: return Prefetch::do_read; aoqi@0: } aoqi@0: }; aoqi@0: aoqi@0: class Par_MarkRefsIntoClosure: public CMSOopsInGenClosure { aoqi@0: private: aoqi@0: const MemRegion _span; aoqi@0: CMSBitMap* _bitMap; aoqi@0: protected: aoqi@0: DO_OOP_WORK_DEFN aoqi@0: public: aoqi@0: Par_MarkRefsIntoClosure(MemRegion span, CMSBitMap* bitMap); aoqi@0: virtual void do_oop(oop* p); aoqi@0: virtual void do_oop(narrowOop* p); aoqi@0: aoqi@0: Prefetch::style prefetch_style() { aoqi@0: return Prefetch::do_read; aoqi@0: } aoqi@0: }; aoqi@0: aoqi@0: // A variant of the above used in certain kinds of CMS aoqi@0: // marking verification. aoqi@0: class MarkRefsIntoVerifyClosure: public CMSOopsInGenClosure { aoqi@0: private: aoqi@0: const MemRegion _span; aoqi@0: CMSBitMap* _verification_bm; aoqi@0: CMSBitMap* _cms_bm; aoqi@0: protected: aoqi@0: DO_OOP_WORK_DEFN aoqi@0: public: aoqi@0: MarkRefsIntoVerifyClosure(MemRegion span, CMSBitMap* verification_bm, aoqi@0: CMSBitMap* cms_bm); aoqi@0: virtual void do_oop(oop* p); aoqi@0: virtual void do_oop(narrowOop* p); aoqi@0: aoqi@0: Prefetch::style prefetch_style() { aoqi@0: return Prefetch::do_read; aoqi@0: } aoqi@0: }; aoqi@0: aoqi@0: // The non-parallel version (the parallel version appears further below). aoqi@0: class PushAndMarkClosure: public CMSOopClosure { aoqi@0: private: aoqi@0: CMSCollector* _collector; aoqi@0: MemRegion _span; aoqi@0: CMSBitMap* _bit_map; aoqi@0: CMSBitMap* _mod_union_table; aoqi@0: CMSMarkStack* _mark_stack; aoqi@0: bool _concurrent_precleaning; aoqi@0: protected: aoqi@0: DO_OOP_WORK_DEFN aoqi@0: public: aoqi@0: PushAndMarkClosure(CMSCollector* collector, aoqi@0: MemRegion span, aoqi@0: ReferenceProcessor* rp, aoqi@0: CMSBitMap* bit_map, aoqi@0: CMSBitMap* mod_union_table, aoqi@0: CMSMarkStack* mark_stack, aoqi@0: bool concurrent_precleaning); aoqi@0: virtual void do_oop(oop* p); aoqi@0: virtual void do_oop(narrowOop* p); aoqi@0: inline void do_oop_nv(oop* p) { PushAndMarkClosure::do_oop_work(p); } aoqi@0: inline void do_oop_nv(narrowOop* p) { PushAndMarkClosure::do_oop_work(p); } aoqi@0: aoqi@0: Prefetch::style prefetch_style() { aoqi@0: return Prefetch::do_read; aoqi@0: } aoqi@0: }; aoqi@0: aoqi@0: // In the parallel case, the bit map and the aoqi@0: // reference processor are currently all shared. Access to aoqi@0: // these shared mutable structures must use appropriate aoqi@0: // synchronization (for instance, via CAS). The marking stack aoqi@0: // used in the non-parallel case above is here replaced with aoqi@0: // an OopTaskQueue structure to allow efficient work stealing. aoqi@0: class Par_PushAndMarkClosure: public CMSOopClosure { aoqi@0: private: aoqi@0: CMSCollector* _collector; aoqi@0: MemRegion _span; aoqi@0: CMSBitMap* _bit_map; aoqi@0: OopTaskQueue* _work_queue; aoqi@0: protected: aoqi@0: DO_OOP_WORK_DEFN aoqi@0: public: aoqi@0: Par_PushAndMarkClosure(CMSCollector* collector, aoqi@0: MemRegion span, aoqi@0: ReferenceProcessor* rp, aoqi@0: CMSBitMap* bit_map, aoqi@0: OopTaskQueue* work_queue); aoqi@0: virtual void do_oop(oop* p); aoqi@0: virtual void do_oop(narrowOop* p); aoqi@0: inline void do_oop_nv(oop* p) { Par_PushAndMarkClosure::do_oop_work(p); } aoqi@0: inline void do_oop_nv(narrowOop* p) { Par_PushAndMarkClosure::do_oop_work(p); } aoqi@0: aoqi@0: Prefetch::style prefetch_style() { aoqi@0: return Prefetch::do_read; aoqi@0: } aoqi@0: }; aoqi@0: aoqi@0: // The non-parallel version (the parallel version appears further below). aoqi@0: class MarkRefsIntoAndScanClosure: public CMSOopsInGenClosure { aoqi@0: private: aoqi@0: MemRegion _span; aoqi@0: CMSBitMap* _bit_map; aoqi@0: CMSMarkStack* _mark_stack; aoqi@0: PushAndMarkClosure _pushAndMarkClosure; aoqi@0: CMSCollector* _collector; aoqi@0: Mutex* _freelistLock; aoqi@0: bool _yield; aoqi@0: // Whether closure is being used for concurrent precleaning aoqi@0: bool _concurrent_precleaning; aoqi@0: protected: aoqi@0: DO_OOP_WORK_DEFN aoqi@0: public: aoqi@0: MarkRefsIntoAndScanClosure(MemRegion span, aoqi@0: ReferenceProcessor* rp, aoqi@0: CMSBitMap* bit_map, aoqi@0: CMSBitMap* mod_union_table, aoqi@0: CMSMarkStack* mark_stack, aoqi@0: CMSCollector* collector, aoqi@0: bool should_yield, aoqi@0: bool concurrent_precleaning); aoqi@0: virtual void do_oop(oop* p); aoqi@0: virtual void do_oop(narrowOop* p); aoqi@0: inline void do_oop_nv(oop* p) { MarkRefsIntoAndScanClosure::do_oop_work(p); } aoqi@0: inline void do_oop_nv(narrowOop* p) { MarkRefsIntoAndScanClosure::do_oop_work(p); } aoqi@0: aoqi@0: Prefetch::style prefetch_style() { aoqi@0: return Prefetch::do_read; aoqi@0: } aoqi@0: void set_freelistLock(Mutex* m) { aoqi@0: _freelistLock = m; aoqi@0: } aoqi@0: aoqi@0: private: aoqi@0: inline void do_yield_check(); aoqi@0: void do_yield_work(); aoqi@0: bool take_from_overflow_list(); aoqi@0: }; aoqi@0: aoqi@0: // Tn this, the parallel avatar of MarkRefsIntoAndScanClosure, the revisit aoqi@0: // stack and the bitMap are shared, so access needs to be suitably aoqi@0: // sycnhronized. An OopTaskQueue structure, supporting efficient aoqi@0: // workstealing, replaces a CMSMarkStack for storing grey objects. aoqi@0: class Par_MarkRefsIntoAndScanClosure: public CMSOopsInGenClosure { aoqi@0: private: aoqi@0: MemRegion _span; aoqi@0: CMSBitMap* _bit_map; aoqi@0: OopTaskQueue* _work_queue; aoqi@0: const uint _low_water_mark; aoqi@0: Par_PushAndMarkClosure _par_pushAndMarkClosure; aoqi@0: protected: aoqi@0: DO_OOP_WORK_DEFN aoqi@0: public: aoqi@0: Par_MarkRefsIntoAndScanClosure(CMSCollector* collector, aoqi@0: MemRegion span, aoqi@0: ReferenceProcessor* rp, aoqi@0: CMSBitMap* bit_map, aoqi@0: OopTaskQueue* work_queue); aoqi@0: virtual void do_oop(oop* p); aoqi@0: virtual void do_oop(narrowOop* p); aoqi@0: inline void do_oop_nv(oop* p) { Par_MarkRefsIntoAndScanClosure::do_oop_work(p); } aoqi@0: inline void do_oop_nv(narrowOop* p) { Par_MarkRefsIntoAndScanClosure::do_oop_work(p); } aoqi@0: aoqi@0: Prefetch::style prefetch_style() { aoqi@0: return Prefetch::do_read; aoqi@0: } aoqi@0: void trim_queue(uint size); aoqi@0: }; aoqi@0: aoqi@0: // This closure is used during the concurrent marking phase aoqi@0: // following the first checkpoint. Its use is buried in aoqi@0: // the closure MarkFromRootsClosure. aoqi@0: class PushOrMarkClosure: public CMSOopClosure { aoqi@0: private: aoqi@0: CMSCollector* _collector; aoqi@0: MemRegion _span; aoqi@0: CMSBitMap* _bitMap; aoqi@0: CMSMarkStack* _markStack; aoqi@0: HeapWord* const _finger; aoqi@0: MarkFromRootsClosure* const aoqi@0: _parent; aoqi@0: protected: aoqi@0: DO_OOP_WORK_DEFN aoqi@0: public: aoqi@0: PushOrMarkClosure(CMSCollector* cms_collector, aoqi@0: MemRegion span, aoqi@0: CMSBitMap* bitMap, aoqi@0: CMSMarkStack* markStack, aoqi@0: HeapWord* finger, aoqi@0: MarkFromRootsClosure* parent); aoqi@0: virtual void do_oop(oop* p); aoqi@0: virtual void do_oop(narrowOop* p); aoqi@0: inline void do_oop_nv(oop* p) { PushOrMarkClosure::do_oop_work(p); } aoqi@0: inline void do_oop_nv(narrowOop* p) { PushOrMarkClosure::do_oop_work(p); } aoqi@0: aoqi@0: // Deal with a stack overflow condition aoqi@0: void handle_stack_overflow(HeapWord* lost); aoqi@0: private: aoqi@0: inline void do_yield_check(); aoqi@0: }; aoqi@0: aoqi@0: // A parallel (MT) version of the above. aoqi@0: // This closure is used during the concurrent marking phase aoqi@0: // following the first checkpoint. Its use is buried in aoqi@0: // the closure Par_MarkFromRootsClosure. aoqi@0: class Par_PushOrMarkClosure: public CMSOopClosure { aoqi@0: private: aoqi@0: CMSCollector* _collector; aoqi@0: MemRegion _whole_span; aoqi@0: MemRegion _span; // local chunk aoqi@0: CMSBitMap* _bit_map; aoqi@0: OopTaskQueue* _work_queue; aoqi@0: CMSMarkStack* _overflow_stack; aoqi@0: HeapWord* const _finger; aoqi@0: HeapWord** const _global_finger_addr; aoqi@0: Par_MarkFromRootsClosure* const aoqi@0: _parent; aoqi@0: protected: aoqi@0: DO_OOP_WORK_DEFN aoqi@0: public: aoqi@0: Par_PushOrMarkClosure(CMSCollector* cms_collector, aoqi@0: MemRegion span, aoqi@0: CMSBitMap* bit_map, aoqi@0: OopTaskQueue* work_queue, aoqi@0: CMSMarkStack* mark_stack, aoqi@0: HeapWord* finger, aoqi@0: HeapWord** global_finger_addr, aoqi@0: Par_MarkFromRootsClosure* parent); aoqi@0: virtual void do_oop(oop* p); aoqi@0: virtual void do_oop(narrowOop* p); aoqi@0: inline void do_oop_nv(oop* p) { Par_PushOrMarkClosure::do_oop_work(p); } aoqi@0: inline void do_oop_nv(narrowOop* p) { Par_PushOrMarkClosure::do_oop_work(p); } aoqi@0: aoqi@0: // Deal with a stack overflow condition aoqi@0: void handle_stack_overflow(HeapWord* lost); aoqi@0: private: aoqi@0: inline void do_yield_check(); aoqi@0: }; aoqi@0: aoqi@0: // For objects in CMS generation, this closure marks aoqi@0: // given objects (transitively) as being reachable/live. aoqi@0: // This is currently used during the (weak) reference object aoqi@0: // processing phase of the CMS final checkpoint step, as aoqi@0: // well as during the concurrent precleaning of the discovered aoqi@0: // reference lists. aoqi@0: class CMSKeepAliveClosure: public CMSOopClosure { aoqi@0: private: aoqi@0: CMSCollector* _collector; aoqi@0: const MemRegion _span; aoqi@0: CMSMarkStack* _mark_stack; aoqi@0: CMSBitMap* _bit_map; aoqi@0: bool _concurrent_precleaning; aoqi@0: protected: aoqi@0: DO_OOP_WORK_DEFN aoqi@0: public: aoqi@0: CMSKeepAliveClosure(CMSCollector* collector, MemRegion span, aoqi@0: CMSBitMap* bit_map, CMSMarkStack* mark_stack, aoqi@0: bool cpc); aoqi@0: bool concurrent_precleaning() const { return _concurrent_precleaning; } aoqi@0: virtual void do_oop(oop* p); aoqi@0: virtual void do_oop(narrowOop* p); aoqi@0: inline void do_oop_nv(oop* p) { CMSKeepAliveClosure::do_oop_work(p); } aoqi@0: inline void do_oop_nv(narrowOop* p) { CMSKeepAliveClosure::do_oop_work(p); } aoqi@0: }; aoqi@0: aoqi@0: class CMSInnerParMarkAndPushClosure: public CMSOopClosure { aoqi@0: private: aoqi@0: CMSCollector* _collector; aoqi@0: MemRegion _span; aoqi@0: OopTaskQueue* _work_queue; aoqi@0: CMSBitMap* _bit_map; aoqi@0: protected: aoqi@0: DO_OOP_WORK_DEFN aoqi@0: public: aoqi@0: CMSInnerParMarkAndPushClosure(CMSCollector* collector, aoqi@0: MemRegion span, CMSBitMap* bit_map, aoqi@0: OopTaskQueue* work_queue); aoqi@0: virtual void do_oop(oop* p); aoqi@0: virtual void do_oop(narrowOop* p); aoqi@0: inline void do_oop_nv(oop* p) { CMSInnerParMarkAndPushClosure::do_oop_work(p); } aoqi@0: inline void do_oop_nv(narrowOop* p) { CMSInnerParMarkAndPushClosure::do_oop_work(p); } aoqi@0: }; aoqi@0: aoqi@0: // A parallel (MT) version of the above, used when aoqi@0: // reference processing is parallel; the only difference aoqi@0: // is in the do_oop method. aoqi@0: class CMSParKeepAliveClosure: public CMSOopClosure { aoqi@0: private: aoqi@0: MemRegion _span; aoqi@0: OopTaskQueue* _work_queue; aoqi@0: CMSBitMap* _bit_map; aoqi@0: CMSInnerParMarkAndPushClosure aoqi@0: _mark_and_push; aoqi@0: const uint _low_water_mark; aoqi@0: void trim_queue(uint max); aoqi@0: protected: aoqi@0: DO_OOP_WORK_DEFN aoqi@0: public: aoqi@0: CMSParKeepAliveClosure(CMSCollector* collector, MemRegion span, aoqi@0: CMSBitMap* bit_map, OopTaskQueue* work_queue); aoqi@0: virtual void do_oop(oop* p); aoqi@0: virtual void do_oop(narrowOop* p); aoqi@0: }; aoqi@0: aoqi@0: #endif // SHARE_VM_GC_IMPLEMENTATION_CONCURRENTMARKSWEEP_CMSOOPCLOSURES_HPP