1 /*
2  * Copyright (c) 2001, 2018, 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_VM_GC_G1_G1OOPCLOSURES_HPP
26 #define SHARE_VM_GC_G1_G1OOPCLOSURES_HPP
27 
28 #include "gc/g1/g1InCSetState.hpp"
29 #include "memory/iterator.hpp"
30 #include "oops/markOop.hpp"
31 
32 class HeapRegion;
33 class G1CollectedHeap;
34 class G1RemSet;
35 class G1ConcurrentMark;
36 class DirtyCardToOopClosure;
37 class G1CMBitMap;
38 class G1ParScanThreadState;
39 class G1ScanEvacuatedObjClosure;
40 class G1CMTask;
41 class ReferenceProcessor;
42 
43 class G1ScanClosureBase : public BasicOopIterateClosure {
44 protected:
45   G1CollectedHeap* _g1h;
46   G1ParScanThreadState* _par_scan_state;
47 
48   G1ScanClosureBase(G1CollectedHeap* g1h, G1ParScanThreadState* par_scan_state);
~G1ScanClosureBase()49   ~G1ScanClosureBase() { }
50 
51   template <class T>
52   inline void prefetch_and_push(T* p, oop const obj);
53 
54   template <class T>
55   inline void handle_non_cset_obj_common(InCSetState const state, T* p, oop const obj);
56 public:
reference_iteration_mode()57   virtual ReferenceIterationMode reference_iteration_mode() { return DO_FIELDS; }
58 
59   inline void trim_queue_partially();
60 };
61 
62 // Used during the Update RS phase to refine remaining cards in the DCQ during garbage collection.
63 class G1ScanObjsDuringUpdateRSClosure : public G1ScanClosureBase {
64 public:
G1ScanObjsDuringUpdateRSClosure(G1CollectedHeap * g1h,G1ParScanThreadState * pss)65   G1ScanObjsDuringUpdateRSClosure(G1CollectedHeap* g1h,
66                                   G1ParScanThreadState* pss) :
67     G1ScanClosureBase(g1h, pss) { }
68 
69   template <class T> void do_oop_work(T* p);
do_oop(narrowOop * p)70   virtual void do_oop(narrowOop* p) { do_oop_work(p); }
do_oop(oop * p)71   virtual void do_oop(oop* p)       { do_oop_work(p); }
72 };
73 
74 // Used during the Scan RS phase to scan cards from the remembered set during garbage collection.
75 class G1ScanObjsDuringScanRSClosure : public G1ScanClosureBase {
76 public:
G1ScanObjsDuringScanRSClosure(G1CollectedHeap * g1h,G1ParScanThreadState * par_scan_state)77   G1ScanObjsDuringScanRSClosure(G1CollectedHeap* g1h,
78                                 G1ParScanThreadState* par_scan_state):
79     G1ScanClosureBase(g1h, par_scan_state) { }
80 
81   template <class T> void do_oop_work(T* p);
do_oop(oop * p)82   virtual void do_oop(oop* p)          { do_oop_work(p); }
do_oop(narrowOop * p)83   virtual void do_oop(narrowOop* p)    { do_oop_work(p); }
84 };
85 
86 // Used during Optional RS scanning to make sure we trim the queues in a timely manner.
87 class G1ScanRSForOptionalClosure : public OopClosure {
88   G1ScanObjsDuringScanRSClosure* _scan_cl;
89 public:
G1ScanRSForOptionalClosure(G1ScanObjsDuringScanRSClosure * cl)90   G1ScanRSForOptionalClosure(G1ScanObjsDuringScanRSClosure* cl) : _scan_cl(cl) { }
91 
92   template <class T> void do_oop_work(T* p);
do_oop(oop * p)93   virtual void do_oop(oop* p)          { do_oop_work(p); }
do_oop(narrowOop * p)94   virtual void do_oop(narrowOop* p)    { do_oop_work(p); }
95 };
96 
97 // This closure is applied to the fields of the objects that have just been copied during evacuation.
98 class G1ScanEvacuatedObjClosure : public G1ScanClosureBase {
99   friend class G1ScanInYoungSetter;
100 
101   enum ScanningInYoungValues {
102     False = 0,
103     True,
104     Uninitialized
105   };
106 
107   ScanningInYoungValues _scanning_in_young;
108 
109 public:
G1ScanEvacuatedObjClosure(G1CollectedHeap * g1h,G1ParScanThreadState * par_scan_state)110   G1ScanEvacuatedObjClosure(G1CollectedHeap* g1h, G1ParScanThreadState* par_scan_state) :
111     G1ScanClosureBase(g1h, par_scan_state), _scanning_in_young(Uninitialized) { }
112 
113   template <class T> void do_oop_work(T* p);
do_oop(oop * p)114   virtual void do_oop(oop* p)          { do_oop_work(p); }
do_oop(narrowOop * p)115   virtual void do_oop(narrowOop* p)    { do_oop_work(p); }
116 
117   // We need to do reference discovery while processing evacuated objects.
reference_iteration_mode()118   virtual ReferenceIterationMode reference_iteration_mode() { return DO_DISCOVERED_AND_DISCOVERY; }
119 
set_ref_discoverer(ReferenceDiscoverer * rd)120   void set_ref_discoverer(ReferenceDiscoverer* rd) {
121     set_ref_discoverer_internal(rd);
122   }
123 };
124 
125 // RAII object to properly set the _scanning_in_young field in G1ScanEvacuatedObjClosure.
126 class G1ScanInYoungSetter : public StackObj {
127   G1ScanEvacuatedObjClosure* _closure;
128 
129 public:
G1ScanInYoungSetter(G1ScanEvacuatedObjClosure * closure,bool new_value)130   G1ScanInYoungSetter(G1ScanEvacuatedObjClosure* closure, bool new_value) : _closure(closure) {
131     assert(_closure->_scanning_in_young == G1ScanEvacuatedObjClosure::Uninitialized, "Must not be set");
132     _closure->_scanning_in_young = new_value ? G1ScanEvacuatedObjClosure::True : G1ScanEvacuatedObjClosure::False;
133   }
134 
~G1ScanInYoungSetter()135   ~G1ScanInYoungSetter() {
136     DEBUG_ONLY(_closure->_scanning_in_young = G1ScanEvacuatedObjClosure::Uninitialized;)
137   }
138 };
139 
140 // Add back base class for metadata
141 class G1ParCopyHelper : public OopClosure {
142 protected:
143   G1CollectedHeap* _g1h;
144   G1ParScanThreadState* _par_scan_state;
145   uint _worker_id;              // Cache value from par_scan_state.
146   ClassLoaderData* _scanned_cld;
147   G1ConcurrentMark* _cm;
148 
149   // Mark the object if it's not already marked. This is used to mark
150   // objects pointed to by roots that are guaranteed not to move
151   // during the GC (i.e., non-CSet objects). It is MT-safe.
152   inline void mark_object(oop obj);
153 
154   G1ParCopyHelper(G1CollectedHeap* g1h,  G1ParScanThreadState* par_scan_state);
~G1ParCopyHelper()155   ~G1ParCopyHelper() { }
156 
157  public:
set_scanned_cld(ClassLoaderData * cld)158   void set_scanned_cld(ClassLoaderData* cld) { _scanned_cld = cld; }
159   inline void do_cld_barrier(oop new_obj);
160 
161   inline void trim_queue_partially();
162 };
163 
164 enum G1Barrier {
165   G1BarrierNone,
166   G1BarrierCLD
167 };
168 
169 enum G1Mark {
170   G1MarkNone,
171   G1MarkFromRoot,
172   G1MarkPromotedFromRoot
173 };
174 
175 template <G1Barrier barrier, G1Mark do_mark_object>
176 class G1ParCopyClosure : public G1ParCopyHelper {
177 public:
G1ParCopyClosure(G1CollectedHeap * g1h,G1ParScanThreadState * par_scan_state)178   G1ParCopyClosure(G1CollectedHeap* g1h, G1ParScanThreadState* par_scan_state) :
179       G1ParCopyHelper(g1h, par_scan_state) { }
180 
181   template <class T> void do_oop_work(T* p);
do_oop(oop * p)182   virtual void do_oop(oop* p)       { do_oop_work(p); }
do_oop(narrowOop * p)183   virtual void do_oop(narrowOop* p) { do_oop_work(p); }
184 };
185 
186 class G1CLDScanClosure : public CLDClosure {
187   G1ParCopyHelper* _closure;
188   bool             _process_only_dirty;
189   int              _claim;
190   int              _count;
191 public:
G1CLDScanClosure(G1ParCopyHelper * closure,bool process_only_dirty,int claim_value)192   G1CLDScanClosure(G1ParCopyHelper* closure,
193                    bool process_only_dirty, int claim_value)
194   : _closure(closure), _process_only_dirty(process_only_dirty), _claim(claim_value), _count(0) {}
195   void do_cld(ClassLoaderData* cld);
196 };
197 
198 // Closure for iterating over object fields during concurrent marking
199 class G1CMOopClosure : public MetadataVisitingOopIterateClosure {
200   G1CollectedHeap*   _g1h;
201   G1CMTask*          _task;
202 public:
203   G1CMOopClosure(G1CollectedHeap* g1h,G1CMTask* task);
204   template <class T> void do_oop_work(T* p);
do_oop(oop * p)205   virtual void do_oop(      oop* p) { do_oop_work(p); }
do_oop(narrowOop * p)206   virtual void do_oop(narrowOop* p) { do_oop_work(p); }
207 };
208 
209 // Closure to scan the root regions during concurrent marking
210 class G1RootRegionScanClosure : public MetadataVisitingOopIterateClosure {
211 private:
212   G1CollectedHeap* _g1h;
213   G1ConcurrentMark* _cm;
214   uint _worker_id;
215 public:
G1RootRegionScanClosure(G1CollectedHeap * g1h,G1ConcurrentMark * cm,uint worker_id)216   G1RootRegionScanClosure(G1CollectedHeap* g1h, G1ConcurrentMark* cm, uint worker_id) :
217     _g1h(g1h), _cm(cm), _worker_id(worker_id) { }
218   template <class T> void do_oop_work(T* p);
do_oop(oop * p)219   virtual void do_oop(      oop* p) { do_oop_work(p); }
do_oop(narrowOop * p)220   virtual void do_oop(narrowOop* p) { do_oop_work(p); }
221 };
222 
223 class G1ConcurrentRefineOopClosure: public BasicOopIterateClosure {
224   G1CollectedHeap* _g1h;
225   uint _worker_i;
226 
227 public:
G1ConcurrentRefineOopClosure(G1CollectedHeap * g1h,uint worker_i)228   G1ConcurrentRefineOopClosure(G1CollectedHeap* g1h, uint worker_i) :
229     _g1h(g1h),
230     _worker_i(worker_i) {
231   }
232 
reference_iteration_mode()233   virtual ReferenceIterationMode reference_iteration_mode() { return DO_FIELDS; }
234 
235   template <class T> void do_oop_work(T* p);
do_oop(narrowOop * p)236   virtual void do_oop(narrowOop* p) { do_oop_work(p); }
do_oop(oop * p)237   virtual void do_oop(oop* p)       { do_oop_work(p); }
238 };
239 
240 class G1RebuildRemSetClosure : public BasicOopIterateClosure {
241   G1CollectedHeap* _g1h;
242   uint _worker_id;
243 public:
G1RebuildRemSetClosure(G1CollectedHeap * g1h,uint worker_id)244   G1RebuildRemSetClosure(G1CollectedHeap* g1h, uint worker_id) : _g1h(g1h), _worker_id(worker_id) {
245   }
246 
247   template <class T> void do_oop_work(T* p);
do_oop(oop * p)248   virtual void do_oop(oop* p)       { do_oop_work(p); }
do_oop(narrowOop * p)249   virtual void do_oop(narrowOop* p) { do_oop_work(p); }
250 
reference_iteration_mode()251   virtual ReferenceIterationMode reference_iteration_mode() { return DO_FIELDS; }
252 };
253 
254 #endif // SHARE_VM_GC_G1_G1OOPCLOSURES_HPP
255