1 /*
  2  * Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved.
  3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4  *
  5  * This code is free software; you can redistribute it and/or modify it
  6  * under the terms of the GNU General Public License version 2 only, as
  7  * published by the Free Software Foundation.
  8  *
  9  * This code is distributed in the hope that it will be useful, but WITHOUT
 10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 12  * version 2 for more details (a copy is included in the LICENSE file that
 13  * accompanied this code).
 14  *
 15  * You should have received a copy of the GNU General Public License version
 16  * 2 along with this work; if not, write to the Free Software Foundation,
 17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 18  *
 19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 20  * or visit www.oracle.com if you need additional information or have any
 21  * questions.
 22  *
 23  */
 24 
 25 #ifndef SHARE_GC_SHARED_GCVMOPERATIONS_HPP
 26 #define SHARE_GC_SHARED_GCVMOPERATIONS_HPP
 27 
 28 #include "gc/shared/collectedHeap.hpp"
 29 #include "gc/shared/genCollectedHeap.hpp"
 30 #include "memory/metaspace.hpp"
 31 #include "prims/jvmtiExport.hpp"
 32 #include "runtime/handles.hpp"
 33 #include "runtime/synchronizer.hpp"
 34 #include "runtime/vmOperation.hpp"
 35 
 36 // The following class hierarchy represents
 37 // a set of operations (VM_Operation) related to GC.
 38 //
 39 //  VM_Operation
 40 //    VM_GC_Sync_Operation
 41 //      VM_GC_Operation
 42 //        VM_GC_HeapInspection
 43 //        VM_PopulateDynamicDumpSharedSpace
 44 //        VM_GenCollectFull
 45 //        VM_GenCollectFullConcurrent
 46 //        VM_ParallelGCSystemGC
 47 //        VM_CollectForAllocation
 48 //          VM_GenCollectForAllocation
 49 //          VM_ParallelGCFailedAllocation
 50 //      VM_Verify
 51 //      VM_PopulateDumpSharedSpace
 52 //
 53 //  VM_GC_Sync_Operation
 54 //   - implements only synchronization with other VM operations of the
 55 //     same kind using the Heap_lock, not actually doing a GC.
 56 //
 57 //  VM_GC_Operation
 58 //   - implements methods common to all operations that perform garbage collections,
 59 //     checking that the VM is in a state to do GC and preventing multiple GC
 60 //     requests.
 61 //
 62 //  VM_GC_HeapInspection
 63 //   - prints class histogram on SIGBREAK if PrintClassHistogram
 64 //     is specified; and also the attach "inspectheap" operation
 65 //
 66 //  VM_CollectForAllocation
 67 //  VM_GenCollectForAllocation
 68 //  VM_ParallelGCFailedAllocation
 69 //   - this operation is invoked when allocation is failed;
 70 //     operation performs garbage collection and tries to
 71 //     allocate afterwards;
 72 //
 73 //  VM_GenCollectFull
 74 //  VM_GenCollectFullConcurrent
 75 //  VM_ParallelGCSystemGC
 76 //   - these operations preform full collection of heaps of
 77 //     different kind
 78 //
 79 //  VM_Verify
 80 //   - verifies the heap
 81 //
 82 //  VM_PopulateDynamicDumpSharedSpace
 83 //   - populates the CDS archive area with the information from the archive file.
 84 //
 85 //  VM_PopulateDumpSharedSpace
 86 //   - creates the CDS archive
 87 //
 88 
 89 class VM_GC_Sync_Operation : public VM_Operation {
 90 public:
 91 
 92   VM_GC_Sync_Operation() : VM_Operation() { }
 93 
 94   // Acquires the Heap_lock.
 95   virtual bool doit_prologue();
 96   // Releases the Heap_lock.
 97   virtual void doit_epilogue();
 98 };
 99 
100 class VM_Verify : public VM_GC_Sync_Operation {
101  public:
102   VMOp_Type type() const { return VMOp_Verify; }
103   void doit();
104 };
105 
106 class VM_GC_Operation: public VM_GC_Sync_Operation {
107  protected:
108   uint           _gc_count_before;         // gc count before acquiring the Heap_lock
109   uint           _full_gc_count_before;    // full gc count before acquiring the Heap_lock
110   bool           _full;                    // whether a "full" collection
111   bool           _prologue_succeeded;      // whether doit_prologue succeeded
112   GCCause::Cause _gc_cause;                // the putative cause for this gc op
113   bool           _gc_locked;               // will be set if gc was locked
114 
115   virtual bool skip_operation() const;
116 
117  public:
118   VM_GC_Operation(uint gc_count_before,
119                   GCCause::Cause _cause,
120                   uint full_gc_count_before = 0,
121                   bool full = false) : VM_GC_Sync_Operation() {
122     _full = full;
123     _prologue_succeeded = false;
124     _gc_count_before    = gc_count_before;
125 
126     // A subclass constructor will likely overwrite the following
127     _gc_cause           = _cause;
128 
129     _gc_locked = false;
130 
131     _full_gc_count_before = full_gc_count_before;
132     // In ParallelScavengeHeap::mem_allocate() collections can be
133     // executed within a loop and _all_soft_refs_clear can be set
134     // true after they have been cleared by a collection and another
135     // collection started so that _all_soft_refs_clear can be true
136     // when this collection is started.  Don't assert that
137     // _all_soft_refs_clear have to be false here even though
138     // mutators have run.  Soft refs will be cleared again in this
139     // collection.
140   }
141   ~VM_GC_Operation();
142 
143   // Acquire the Heap_lock and determine if this VM operation should be executed
144   // (i.e. not skipped). Return this result, and also store it in _prologue_succeeded.
145   virtual bool doit_prologue();
146   // Notify the Heap_lock if needed and release it.
147   virtual void doit_epilogue();
148 
149   virtual bool allow_nested_vm_operations() const  { return true; }
150   bool prologue_succeeded() const { return _prologue_succeeded; }
151 
152   void set_gc_locked() { _gc_locked = true; }
153   bool gc_locked() const  { return _gc_locked; }
154 
155   static void notify_gc_begin(bool full = false);
156   static void notify_gc_end();
157 };
158 
159 
160 class VM_GC_HeapInspection: public VM_GC_Operation {
161  private:
162   outputStream* _out;
163   bool _full_gc;
164   uint _parallel_thread_num;
165  public:
166   VM_GC_HeapInspection(outputStream* out, bool request_full_gc,
167                        uint parallel_thread_num = 1) :
168     VM_GC_Operation(0 /* total collections,      dummy, ignored */,
169                     GCCause::_heap_inspection /* GC Cause */,
170                     0 /* total full collections, dummy, ignored */,
171                     request_full_gc), _out(out), _full_gc(request_full_gc),
172                     _parallel_thread_num(parallel_thread_num) {}
173 
174   ~VM_GC_HeapInspection() {}
175   virtual VMOp_Type type() const { return VMOp_GC_HeapInspection; }
176   virtual bool skip_operation() const;
177   virtual void doit();
178  protected:
179   bool collect();
180 };
181 
182 class VM_CollectForAllocation : public VM_GC_Operation {
183  protected:
184   size_t    _word_size; // Size of object to be allocated (in number of words)
185   HeapWord* _result;    // Allocation result (NULL if allocation failed)
186 
187  public:
188   VM_CollectForAllocation(size_t word_size, uint gc_count_before, GCCause::Cause cause);
189 
190   HeapWord* result() const {
191     return _result;
192   }
193 };
194 
195 class VM_GenCollectForAllocation : public VM_CollectForAllocation {
196  private:
197   bool        _tlab;                       // alloc is of a tlab.
198  public:
199   VM_GenCollectForAllocation(size_t word_size,
200                              bool tlab,
201                              uint gc_count_before)
202     : VM_CollectForAllocation(word_size, gc_count_before, GCCause::_allocation_failure),
203       _tlab(tlab) {
204     assert(word_size != 0, "An allocation should always be requested with this operation.");
205   }
206   ~VM_GenCollectForAllocation()  {}
207   virtual VMOp_Type type() const { return VMOp_GenCollectForAllocation; }
208   virtual void doit();
209 };
210 
211 // VM operation to invoke a collection of the heap as a
212 // GenCollectedHeap heap.
213 class VM_GenCollectFull: public VM_GC_Operation {
214  private:
215   GenCollectedHeap::GenerationType _max_generation;
216  public:
217   VM_GenCollectFull(uint gc_count_before,
218                     uint full_gc_count_before,
219                     GCCause::Cause gc_cause,
220                     GenCollectedHeap::GenerationType max_generation)
221     : VM_GC_Operation(gc_count_before, gc_cause, full_gc_count_before,
222                       max_generation != GenCollectedHeap::YoungGen /* full */),
223       _max_generation(max_generation) { }
224   ~VM_GenCollectFull() {}
225   virtual VMOp_Type type() const { return VMOp_GenCollectFull; }
226   virtual void doit();
227 };
228 
229 class VM_CollectForMetadataAllocation: public VM_GC_Operation {
230  private:
231   MetaWord*                _result;
232   size_t                   _size;     // size of object to be allocated
233   Metaspace::MetadataType  _mdtype;
234   ClassLoaderData*         _loader_data;
235 
236  public:
237   VM_CollectForMetadataAllocation(ClassLoaderData* loader_data,
238                                   size_t size,
239                                   Metaspace::MetadataType mdtype,
240                                   uint gc_count_before,
241                                   uint full_gc_count_before,
242                                   GCCause::Cause gc_cause);
243 
244   virtual VMOp_Type type() const { return VMOp_CollectForMetadataAllocation; }
245   virtual void doit();
246   MetaWord* result() const       { return _result; }
247 };
248 
249 class VM_CollectForCodeCacheAllocation: public VM_GC_Operation {
250 public:
251   VM_CollectForCodeCacheAllocation(uint gc_count_before,
252                                    uint full_gc_count_before,
253                                    GCCause::Cause gc_cause);
254 
255   virtual VMOp_Type type() const { return VMOp_CollectForCodeCacheAllocation; }
256   virtual void doit();
257 };
258 
259 class SvcGCMarker : public StackObj {
260  private:
261   JvmtiGCMarker _jgcm;
262  public:
263   typedef enum { MINOR, FULL, CONCURRENT } reason_type;
264 
265   SvcGCMarker(reason_type reason ) {
266     VM_GC_Operation::notify_gc_begin(reason == FULL);
267   }
268 
269   ~SvcGCMarker() {
270     VM_GC_Operation::notify_gc_end();
271   }
272 };
273 
274 #endif // SHARE_GC_SHARED_GCVMOPERATIONS_HPP
--- EOF ---