aoqi@0: /* aoqi@0: * Copyright (c) 2000, 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_MEMORY_SHAREDHEAP_HPP aoqi@0: #define SHARE_VM_MEMORY_SHAREDHEAP_HPP aoqi@0: aoqi@0: #include "gc_interface/collectedHeap.hpp" aoqi@0: #include "memory/generation.hpp" aoqi@0: aoqi@0: // A "SharedHeap" is an implementation of a java heap for HotSpot. This aoqi@0: // is an abstract class: there may be many different kinds of heaps. This aoqi@0: // class defines the functions that a heap must implement, and contains aoqi@0: // infrastructure common to all heaps. aoqi@0: aoqi@0: class Generation; aoqi@0: class BarrierSet; aoqi@0: class GenRemSet; aoqi@0: class Space; aoqi@0: class SpaceClosure; aoqi@0: class OopClosure; aoqi@0: class OopsInGenClosure; aoqi@0: class ObjectClosure; aoqi@0: class SubTasksDone; aoqi@0: class WorkGang; aoqi@0: class FlexibleWorkGang; aoqi@0: class CollectorPolicy; aoqi@0: class KlassClosure; aoqi@0: aoqi@0: // Note on use of FlexibleWorkGang's for GC. aoqi@0: // There are three places where task completion is determined. aoqi@0: // In aoqi@0: // 1) ParallelTaskTerminator::offer_termination() where _n_threads aoqi@0: // must be set to the correct value so that count of workers that aoqi@0: // have offered termination will exactly match the number aoqi@0: // working on the task. Tasks such as those derived from GCTask aoqi@0: // use ParallelTaskTerminator's. Tasks that want load balancing aoqi@0: // by work stealing use this method to gauge completion. aoqi@0: // 2) SubTasksDone has a variable _n_threads that is used in aoqi@0: // all_tasks_completed() to determine completion. all_tasks_complete() aoqi@0: // counts the number of tasks that have been done and then reset aoqi@0: // the SubTasksDone so that it can be used again. When the number of aoqi@0: // tasks is set to the number of GC workers, then _n_threads must aoqi@0: // be set to the number of active GC workers. G1CollectedHeap, aoqi@0: // HRInto_G1RemSet, GenCollectedHeap and SharedHeap have SubTasksDone. aoqi@0: // This seems too many. aoqi@0: // 3) SequentialSubTasksDone has an _n_threads that is used in aoqi@0: // a way similar to SubTasksDone and has the same dependency on the aoqi@0: // number of active GC workers. CompactibleFreeListSpace and Space aoqi@0: // have SequentialSubTasksDone's. aoqi@0: // Example of using SubTasksDone and SequentialSubTasksDone aoqi@0: // G1CollectedHeap::g1_process_strong_roots() calls aoqi@0: // process_strong_roots(false, // no scoping; this is parallel code aoqi@0: // is_scavenging, so, aoqi@0: // &buf_scan_non_heap_roots, aoqi@0: // &eager_scan_code_roots); aoqi@0: // which delegates to SharedHeap::process_strong_roots() and uses aoqi@0: // SubTasksDone* _process_strong_tasks to claim tasks. aoqi@0: // process_strong_roots() calls aoqi@0: // rem_set()->younger_refs_iterate() aoqi@0: // to scan the card table and which eventually calls down into aoqi@0: // CardTableModRefBS::par_non_clean_card_iterate_work(). This method aoqi@0: // uses SequentialSubTasksDone* _pst to claim tasks. aoqi@0: // Both SubTasksDone and SequentialSubTasksDone call their method aoqi@0: // all_tasks_completed() to count the number of GC workers that have aoqi@0: // finished their work. That logic is "when all the workers are aoqi@0: // finished the tasks are finished". aoqi@0: // aoqi@0: // The pattern that appears in the code is to set _n_threads aoqi@0: // to a value > 1 before a task that you would like executed in parallel aoqi@0: // and then to set it to 0 after that task has completed. A value of aoqi@0: // 0 is a "special" value in set_n_threads() which translates to aoqi@0: // setting _n_threads to 1. aoqi@0: // aoqi@0: // Some code uses _n_terminiation to decide if work should be done in aoqi@0: // parallel. The notorious possibly_parallel_oops_do() in threads.cpp aoqi@0: // is an example of such code. Look for variable "is_par" for other aoqi@0: // examples. aoqi@0: // aoqi@0: // The active_workers is not reset to 0 after a parallel phase. It's aoqi@0: // value may be used in later phases and in one instance at least aoqi@0: // (the parallel remark) it has to be used (the parallel remark depends aoqi@0: // on the partitioning done in the previous parallel scavenge). aoqi@0: aoqi@0: class SharedHeap : public CollectedHeap { aoqi@0: friend class VMStructs; aoqi@0: aoqi@0: friend class VM_GC_Operation; aoqi@0: friend class VM_CGC_Operation; aoqi@0: aoqi@0: private: aoqi@0: // For claiming strong_roots tasks. aoqi@0: SubTasksDone* _process_strong_tasks; aoqi@0: aoqi@0: protected: aoqi@0: // There should be only a single instance of "SharedHeap" in a program. aoqi@0: // This is enforced with the protected constructor below, which will also aoqi@0: // set the static pointer "_sh" to that instance. aoqi@0: static SharedHeap* _sh; aoqi@0: aoqi@0: // and the Gen Remembered Set, at least one good enough to scan the perm aoqi@0: // gen. aoqi@0: GenRemSet* _rem_set; aoqi@0: aoqi@0: // A gc policy, controls global gc resource issues aoqi@0: CollectorPolicy *_collector_policy; aoqi@0: aoqi@0: // See the discussion below, in the specification of the reader function aoqi@0: // for this variable. aoqi@0: int _strong_roots_parity; aoqi@0: aoqi@0: // If we're doing parallel GC, use this gang of threads. aoqi@0: FlexibleWorkGang* _workers; aoqi@0: aoqi@0: // Full initialization is done in a concrete subtype's "initialize" aoqi@0: // function. aoqi@0: SharedHeap(CollectorPolicy* policy_); aoqi@0: aoqi@0: // Returns true if the calling thread holds the heap lock, aoqi@0: // or the calling thread is a par gc thread and the heap_lock is held aoqi@0: // by the vm thread doing a gc operation. aoqi@0: bool heap_lock_held_for_gc(); aoqi@0: // True if the heap_lock is held by the a non-gc thread invoking a gc aoqi@0: // operation. aoqi@0: bool _thread_holds_heap_lock_for_gc; aoqi@0: aoqi@0: public: aoqi@0: static SharedHeap* heap() { return _sh; } aoqi@0: aoqi@0: void set_barrier_set(BarrierSet* bs); aoqi@0: SubTasksDone* process_strong_tasks() { return _process_strong_tasks; } aoqi@0: aoqi@0: // Does operations required after initialization has been done. aoqi@0: virtual void post_initialize(); aoqi@0: aoqi@0: // Initialization of ("weak") reference processing support aoqi@0: virtual void ref_processing_init(); aoqi@0: aoqi@0: // This function returns the "GenRemSet" object that allows us to scan aoqi@0: // generations in a fully generational heap. aoqi@0: GenRemSet* rem_set() { return _rem_set; } aoqi@0: aoqi@0: // Iteration functions. aoqi@0: void oop_iterate(ExtendedOopClosure* cl) = 0; aoqi@0: aoqi@0: // Same as above, restricted to a memory region. aoqi@0: virtual void oop_iterate(MemRegion mr, ExtendedOopClosure* cl) = 0; aoqi@0: aoqi@0: // Iterate over all spaces in use in the heap, in an undefined order. aoqi@0: virtual void space_iterate(SpaceClosure* cl) = 0; aoqi@0: aoqi@0: // A SharedHeap will contain some number of spaces. This finds the aoqi@0: // space whose reserved area contains the given address, or else returns aoqi@0: // NULL. aoqi@0: virtual Space* space_containing(const void* addr) const = 0; aoqi@0: aoqi@0: bool no_gc_in_progress() { return !is_gc_active(); } aoqi@0: aoqi@0: // Some collectors will perform "process_strong_roots" in parallel. aoqi@0: // Such a call will involve claiming some fine-grained tasks, such as aoqi@0: // scanning of threads. To make this process simpler, we provide the aoqi@0: // "strong_roots_parity()" method. Collectors that start parallel tasks aoqi@0: // whose threads invoke "process_strong_roots" must aoqi@0: // call "change_strong_roots_parity" in sequential code starting such a aoqi@0: // task. (This also means that a parallel thread may only call aoqi@0: // process_strong_roots once.) aoqi@0: // aoqi@0: // For calls to process_strong_roots by sequential code, the parity is aoqi@0: // updated automatically. aoqi@0: // aoqi@0: // The idea is that objects representing fine-grained tasks, such as aoqi@0: // threads, will contain a "parity" field. A task will is claimed in the aoqi@0: // current "process_strong_roots" call only if its parity field is the aoqi@0: // same as the "strong_roots_parity"; task claiming is accomplished by aoqi@0: // updating the parity field to the strong_roots_parity with a CAS. aoqi@0: // aoqi@0: // If the client meats this spec, then strong_roots_parity() will have aoqi@0: // the following properties: aoqi@0: // a) to return a different value than was returned before the last aoqi@0: // call to change_strong_roots_parity, and aoqi@0: // c) to never return a distinguished value (zero) with which such aoqi@0: // task-claiming variables may be initialized, to indicate "never aoqi@0: // claimed". aoqi@0: private: aoqi@0: void change_strong_roots_parity(); aoqi@0: public: aoqi@0: int strong_roots_parity() { return _strong_roots_parity; } aoqi@0: aoqi@0: // Call these in sequential code around process_strong_roots. aoqi@0: // strong_roots_prologue calls change_strong_roots_parity, if aoqi@0: // parallel tasks are enabled. aoqi@0: class StrongRootsScope : public MarkingCodeBlobClosure::MarkScope { aoqi@0: public: aoqi@0: StrongRootsScope(SharedHeap* outer, bool activate = true); aoqi@0: ~StrongRootsScope(); aoqi@0: }; aoqi@0: friend class StrongRootsScope; aoqi@0: aoqi@0: enum ScanningOption { aoqi@0: SO_None = 0x0, aoqi@0: SO_AllClasses = 0x1, aoqi@0: SO_SystemClasses = 0x2, aoqi@0: SO_Strings = 0x4, aoqi@0: SO_CodeCache = 0x8 aoqi@0: }; aoqi@0: aoqi@0: FlexibleWorkGang* workers() const { return _workers; } aoqi@0: aoqi@0: // Invoke the "do_oop" method the closure "roots" on all root locations. aoqi@0: // The "so" argument determines which roots the closure is applied to: aoqi@0: // "SO_None" does none; aoqi@0: // "SO_AllClasses" applies the closure to all entries in the SystemDictionary; aoqi@0: // "SO_SystemClasses" to all the "system" classes and loaders; aoqi@0: // "SO_Strings" applies the closure to all entries in StringTable; aoqi@0: // "SO_CodeCache" applies the closure to all elements of the CodeCache. aoqi@0: void process_strong_roots(bool activate_scope, aoqi@0: bool is_scavenging, aoqi@0: ScanningOption so, aoqi@0: OopClosure* roots, aoqi@0: CodeBlobClosure* code_roots, aoqi@0: KlassClosure* klass_closure); aoqi@0: aoqi@0: // Apply "blk" to all the weak roots of the system. These include aoqi@0: // JNI weak roots, the code cache, system dictionary, symbol table, aoqi@0: // string table. aoqi@0: void process_weak_roots(OopClosure* root_closure, aoqi@0: CodeBlobClosure* code_roots); aoqi@0: aoqi@0: // The functions below are helper functions that a subclass of aoqi@0: // "SharedHeap" can use in the implementation of its virtual aoqi@0: // functions. aoqi@0: aoqi@0: public: aoqi@0: aoqi@0: // Do anything common to GC's. aoqi@0: virtual void gc_prologue(bool full) = 0; aoqi@0: virtual void gc_epilogue(bool full) = 0; aoqi@0: aoqi@0: // Sets the number of parallel threads that will be doing tasks aoqi@0: // (such as process strong roots) subsequently. aoqi@0: virtual void set_par_threads(uint t); aoqi@0: aoqi@0: int n_termination(); aoqi@0: void set_n_termination(int t); aoqi@0: aoqi@0: // aoqi@0: // New methods from CollectedHeap aoqi@0: // aoqi@0: aoqi@0: // Some utilities. aoqi@0: void print_size_transition(outputStream* out, aoqi@0: size_t bytes_before, aoqi@0: size_t bytes_after, aoqi@0: size_t capacity); aoqi@0: }; aoqi@0: aoqi@0: #endif // SHARE_VM_MEMORY_SHAREDHEAP_HPP