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_ParallelGCSystemGC
 46 //        VM_CollectForAllocation
 47 //          VM_GenCollectForAllocation
 48 //          VM_ParallelGCFailedAllocation
 49 //      VM_Verify
 50 //      VM_PopulateDumpSharedSpace
 51 //
 52 //  VM_GC_Sync_Operation
 53 //   - implements only synchronization with other VM operations of the
 54 //     same kind using the Heap_lock, not actually doing a GC.
 55 //
 56 //  VM_GC_Operation
 57 //   - implements methods common to all operations that perform garbage collections,
 58 //     checking that the VM is in a state to do GC and preventing multiple GC
 59 //     requests.
 60 //
 61 //  VM_GC_HeapInspection
 62 //   - prints class histogram on SIGBREAK if PrintClassHistogram
 63 //     is specified; and also the attach "inspectheap" operation
 64 //
 65 //  VM_CollectForAllocation
 66 //  VM_GenCollectForAllocation
 67 //  VM_ParallelGCFailedAllocation
 68 //   - this operation is invoked when allocation is failed;
 69 //     operation performs garbage collection and tries to
 70 //     allocate afterwards;
 71 //
 72 //  VM_GenCollectFull
 73 //  VM_ParallelGCSystemGC
 74 //   - these operations preform full collection of heaps of
 75 //     different kind
 76 //
 77 //  VM_Verify
 78 //   - verifies the heap
 79 //
 80 //  VM_PopulateDynamicDumpSharedSpace
 81 //   - populates the CDS archive area with the information from the archive file.
 82 //
 83 //  VM_PopulateDumpSharedSpace
 84 //   - creates the CDS archive
 85 //
 86 
 87 class VM_GC_Sync_Operation : public VM_Operation {
 88 public:
 89 
 90   VM_GC_Sync_Operation() : VM_Operation() { }
 91 
 92   // Acquires the Heap_lock.
 93   virtual bool doit_prologue();
 94   // Releases the Heap_lock.
 95   virtual void doit_epilogue();
 96 };
 97 
 98 class VM_Verify : public VM_GC_Sync_Operation {
 99  public:
100   VMOp_Type type() const { return VMOp_Verify; }
101   void doit();
102 };
103 
104 class VM_GC_Operation: public VM_GC_Sync_Operation {
105  protected:
106   uint           _gc_count_before;         // gc count before acquiring the Heap_lock
107   uint           _full_gc_count_before;    // full gc count before acquiring the Heap_lock
108   bool           _full;                    // whether a "full" collection
109   bool           _prologue_succeeded;      // whether doit_prologue succeeded
110   GCCause::Cause _gc_cause;                // the putative cause for this gc op
111   bool           _gc_locked;               // will be set if gc was locked
112 
113   virtual bool skip_operation() const;
114 
115  public:
116   VM_GC_Operation(uint gc_count_before,
117                   GCCause::Cause _cause,
118                   uint full_gc_count_before = 0,
119                   bool full = false) : VM_GC_Sync_Operation() {
120     _full = full;
121     _prologue_succeeded = false;
122     _gc_count_before    = gc_count_before;
123 
124     // A subclass constructor will likely overwrite the following
125     _gc_cause           = _cause;
126 
127     _gc_locked = false;
128 
129     _full_gc_count_before = full_gc_count_before;
130     // In ParallelScavengeHeap::mem_allocate() collections can be
131     // executed within a loop and _all_soft_refs_clear can be set
132     // true after they have been cleared by a collection and another
133     // collection started so that _all_soft_refs_clear can be true
134     // when this collection is started.  Don't assert that
135     // _all_soft_refs_clear have to be false here even though
136     // mutators have run.  Soft refs will be cleared again in this
137     // collection.
138   }
139   ~VM_GC_Operation();
140 
141   // Acquire the Heap_lock and determine if this VM operation should be executed
142   // (i.e. not skipped). Return this result, and also store it in _prologue_succeeded.
143   virtual bool doit_prologue();
144   // Notify the Heap_lock if needed and release it.
145   virtual void doit_epilogue();
146 
147   virtual bool allow_nested_vm_operations() const  { return true; }
148   bool prologue_succeeded() const { return _prologue_succeeded; }
149 
150   void set_gc_locked() { _gc_locked = true; }
151   bool gc_locked() const  { return _gc_locked; }
152 
153   static void notify_gc_begin(bool full = false);
154   static void notify_gc_end();
155 };
156 
157 
158 class VM_GC_HeapInspection: public VM_GC_Operation {
159  private:
160   outputStream* _out;
161   bool _full_gc;
162   uint _parallel_thread_num;
163  public:
164   VM_GC_HeapInspection(outputStream* out, bool request_full_gc,
165                        uint parallel_thread_num = 1) :
166     VM_GC_Operation(0 /* total collections,      dummy, ignored */,
167                     GCCause::_heap_inspection /* GC Cause */,
168                     0 /* total full collections, dummy, ignored */,
169                     request_full_gc), _out(out), _full_gc(request_full_gc),
170                     _parallel_thread_num(parallel_thread_num) {}
171 
172   ~VM_GC_HeapInspection() {}
173   virtual VMOp_Type type() const { return VMOp_GC_HeapInspection; }
174   virtual bool skip_operation() const;
175   virtual void doit();
176  protected:
177   bool collect();
178 };
179 
180 class VM_CollectForAllocation : public VM_GC_Operation {
181  protected:
182   size_t    _word_size; // Size of object to be allocated (in number of words)
183   HeapWord* _result;    // Allocation result (NULL if allocation failed)
184 
185  public:
186   VM_CollectForAllocation(size_t word_size, uint gc_count_before, GCCause::Cause cause);
187 
188   HeapWord* result() const {
189     return _result;
190   }
191 };
192 
193 class VM_GenCollectForAllocation : public VM_CollectForAllocation {
194  private:
195   bool        _tlab;                       // alloc is of a tlab.
196  public:
197   VM_GenCollectForAllocation(size_t word_size,
198                              bool tlab,
199                              uint gc_count_before)
200     : VM_CollectForAllocation(word_size, gc_count_before, GCCause::_allocation_failure),
201       _tlab(tlab) {
202     assert(word_size != 0, "An allocation should always be requested with this operation.");
203   }
204   ~VM_GenCollectForAllocation()  {}
205   virtual VMOp_Type type() const { return VMOp_GenCollectForAllocation; }
206   virtual void doit();
207 };
208 
209 // VM operation to invoke a collection of the heap as a
210 // GenCollectedHeap heap.
211 class VM_GenCollectFull: public VM_GC_Operation {
212  private:
213   GenCollectedHeap::GenerationType _max_generation;
214  public:
215   VM_GenCollectFull(uint gc_count_before,
216                     uint full_gc_count_before,
217                     GCCause::Cause gc_cause,
218                     GenCollectedHeap::GenerationType max_generation)
219     : VM_GC_Operation(gc_count_before, gc_cause, full_gc_count_before,
220                       max_generation != GenCollectedHeap::YoungGen /* full */),
221       _max_generation(max_generation) { }
222   ~VM_GenCollectFull() {}
223   virtual VMOp_Type type() const { return VMOp_GenCollectFull; }
224   virtual void doit();
225 };
226 
227 class VM_CollectForMetadataAllocation: public VM_GC_Operation {
228  private:
229   MetaWord*                _result;
230   size_t                   _size;     // size of object to be allocated
231   Metaspace::MetadataType  _mdtype;
232   ClassLoaderData*         _loader_data;
233 
234  public:
235   VM_CollectForMetadataAllocation(ClassLoaderData* loader_data,
236                                   size_t size,
237                                   Metaspace::MetadataType mdtype,
238                                   uint gc_count_before,
239                                   uint full_gc_count_before,
240                                   GCCause::Cause gc_cause);
241 
242   virtual VMOp_Type type() const { return VMOp_CollectForMetadataAllocation; }
243   virtual void doit();
244   MetaWord* result() const       { return _result; }
245 };
246 
247 class SvcGCMarker : public StackObj {
248  private:
249   JvmtiGCMarker _jgcm;
250  public:
251   typedef enum { MINOR, FULL, CONCURRENT } reason_type;
252 
253   SvcGCMarker(reason_type reason ) {
254     VM_GC_Operation::notify_gc_begin(reason == FULL);
255   }
256 
257   ~SvcGCMarker() {
258     VM_GC_Operation::notify_gc_end();
259   }
260 };
261 
262 #endif // SHARE_GC_SHARED_GCVMOPERATIONS_HPP