Tue, 19 May 2009 04:05:31 -0700
6819065: G1: eliminate high serial card table clearing time
Reviewed-by: iveresov, tonyp
1 /*
2 * Copyright 2001-2009 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
20 * CA 95054 USA or visit www.sun.com if you need additional information or
21 * have any questions.
22 *
23 */
25 // A G1RemSet provides ways of iterating over pointers into a selected
26 // collection set.
28 class G1CollectedHeap;
29 class CardTableModRefBarrierSet;
30 class HRInto_G1RemSet;
31 class ConcurrentG1Refine;
33 class G1RemSet: public CHeapObj {
34 protected:
35 G1CollectedHeap* _g1;
36 unsigned _conc_refine_cards;
37 size_t n_workers();
39 public:
40 G1RemSet(G1CollectedHeap* g1) :
41 _g1(g1), _conc_refine_cards(0)
42 {}
44 // Invoke "blk->do_oop" on all pointers into the CS in object in regions
45 // outside the CS (having invoked "blk->set_region" to set the "from"
46 // region correctly beforehand.) The "worker_i" param is for the
47 // parallel case where the number of the worker thread calling this
48 // function can be helpful in partitioning the work to be done. It
49 // should be the same as the "i" passed to the calling thread's
50 // work(i) function. In the sequential case this param will be ingored.
51 virtual void oops_into_collection_set_do(OopsInHeapRegionClosure* blk,
52 int worker_i) = 0;
54 // Prepare for and cleanup after an oops_into_collection_set_do
55 // call. Must call each of these once before and after (in sequential
56 // code) any threads call oops into collection set do. (This offers an
57 // opportunity to sequential setup and teardown of structures needed by a
58 // parallel iteration over the CS's RS.)
59 virtual void prepare_for_oops_into_collection_set_do() = 0;
60 virtual void cleanup_after_oops_into_collection_set_do() = 0;
62 // If "this" is of the given subtype, return "this", else "NULL".
63 virtual HRInto_G1RemSet* as_HRInto_G1RemSet() { return NULL; }
65 // Record, if necessary, the fact that *p (where "p" is in region "from")
66 // has changed to its new value.
67 virtual void write_ref(HeapRegion* from, oop* p) = 0;
68 virtual void par_write_ref(HeapRegion* from, oop* p, int tid) = 0;
70 // Requires "region_bm" and "card_bm" to be bitmaps with 1 bit per region
71 // or card, respectively, such that a region or card with a corresponding
72 // 0 bit contains no part of any live object. Eliminates any remembered
73 // set entries that correspond to dead heap ranges.
74 virtual void scrub(BitMap* region_bm, BitMap* card_bm) = 0;
75 // Like the above, but assumes is called in parallel: "worker_num" is the
76 // parallel thread id of the current thread, and "claim_val" is the
77 // value that should be used to claim heap regions.
78 virtual void scrub_par(BitMap* region_bm, BitMap* card_bm,
79 int worker_num, int claim_val) = 0;
81 // Refine the card corresponding to "card_ptr". If "sts" is non-NULL,
82 // join and leave around parts that must be atomic wrt GC. (NULL means
83 // being done at a safepoint.)
84 virtual void concurrentRefineOneCard(jbyte* card_ptr, int worker_i) {}
86 // Print any relevant summary info.
87 virtual void print_summary_info() {}
89 // Prepare remebered set for verification.
90 virtual void prepare_for_verify() {};
91 };
94 // The simplest possible G1RemSet: iterates over all objects in non-CS
95 // regions, searching for pointers into the CS.
96 class StupidG1RemSet: public G1RemSet {
97 public:
98 StupidG1RemSet(G1CollectedHeap* g1) : G1RemSet(g1) {}
100 void oops_into_collection_set_do(OopsInHeapRegionClosure* blk,
101 int worker_i);
103 void prepare_for_oops_into_collection_set_do() {}
104 void cleanup_after_oops_into_collection_set_do() {}
106 // Nothing is necessary in the version below.
107 void write_ref(HeapRegion* from, oop* p) {}
108 void par_write_ref(HeapRegion* from, oop* p, int tid) {}
110 void scrub(BitMap* region_bm, BitMap* card_bm) {}
111 void scrub_par(BitMap* region_bm, BitMap* card_bm,
112 int worker_num, int claim_val) {}
114 };
116 // A G1RemSet in which each heap region has a rem set that records the
117 // external heap references into it. Uses a mod ref bs to track updates,
118 // so that they can be used to update the individual region remsets.
120 class HRInto_G1RemSet: public G1RemSet {
121 protected:
122 enum SomePrivateConstants {
123 UpdateRStoMergeSync = 0,
124 MergeRStoDoDirtySync = 1,
125 DoDirtySync = 2,
126 LastSync = 3,
128 SeqTask = 0,
129 NumSeqTasks = 1
130 };
132 CardTableModRefBS* _ct_bs;
133 SubTasksDone* _seq_task;
134 G1CollectorPolicy* _g1p;
136 ConcurrentG1Refine* _cg1r;
138 size_t* _cards_scanned;
139 size_t _total_cards_scanned;
141 // _par_traversal_in_progress is "true" iff a parallel traversal is in
142 // progress. If so, then cards added to remembered sets should also have
143 // their references into the collection summarized in "_new_refs".
144 bool _par_traversal_in_progress;
145 void set_par_traversal(bool b) { _par_traversal_in_progress = b; }
146 GrowableArray<oop*>** _new_refs;
147 void new_refs_iterate(OopClosure* cl);
149 public:
150 // This is called to reset dual hash tables after the gc pause
151 // is finished and the initial hash table is no longer being
152 // scanned.
153 void cleanupHRRS();
155 HRInto_G1RemSet(G1CollectedHeap* g1, CardTableModRefBS* ct_bs);
156 ~HRInto_G1RemSet();
158 void oops_into_collection_set_do(OopsInHeapRegionClosure* blk,
159 int worker_i);
161 void prepare_for_oops_into_collection_set_do();
162 void cleanup_after_oops_into_collection_set_do();
163 void scanRS(OopsInHeapRegionClosure* oc, int worker_i);
164 void scanNewRefsRS(OopsInHeapRegionClosure* oc, int worker_i);
165 void updateRS(int worker_i);
166 HeapRegion* calculateStartRegion(int i);
168 HRInto_G1RemSet* as_HRInto_G1RemSet() { return this; }
170 CardTableModRefBS* ct_bs() { return _ct_bs; }
171 size_t cardsScanned() { return _total_cards_scanned; }
173 // Record, if necessary, the fact that *p (where "p" is in region "from",
174 // which is required to be non-NULL) has changed to a new non-NULL value.
175 inline void write_ref(HeapRegion* from, oop* p);
176 // The "_nv" version is the same; it exists just so that it is not virtual.
177 inline void write_ref_nv(HeapRegion* from, oop* p);
179 inline bool self_forwarded(oop obj);
180 inline void par_write_ref(HeapRegion* from, oop* p, int tid);
182 void scrub(BitMap* region_bm, BitMap* card_bm);
183 void scrub_par(BitMap* region_bm, BitMap* card_bm,
184 int worker_num, int claim_val);
186 virtual void concurrentRefineOneCard(jbyte* card_ptr, int worker_i);
188 virtual void print_summary_info();
189 virtual void prepare_for_verify();
190 };
192 #define G1_REM_SET_LOGGING 0
194 class CountNonCleanMemRegionClosure: public MemRegionClosure {
195 G1CollectedHeap* _g1;
196 int _n;
197 HeapWord* _start_first;
198 public:
199 CountNonCleanMemRegionClosure(G1CollectedHeap* g1) :
200 _g1(g1), _n(0), _start_first(NULL)
201 {}
202 void do_MemRegion(MemRegion mr);
203 int n() { return _n; };
204 HeapWord* start_first() { return _start_first; }
205 };
207 class UpdateRSOopClosure: public OopClosure {
208 HeapRegion* _from;
209 HRInto_G1RemSet* _rs;
210 int _worker_i;
211 public:
212 UpdateRSOopClosure(HRInto_G1RemSet* rs, int worker_i = 0) :
213 _from(NULL), _rs(rs), _worker_i(worker_i) {
214 guarantee(_rs != NULL, "Requires an HRIntoG1RemSet");
215 }
217 void set_from(HeapRegion* from) {
218 assert(from != NULL, "from region must be non-NULL");
219 _from = from;
220 }
222 virtual void do_oop(narrowOop* p);
223 virtual void do_oop(oop* p);
225 // Override: this closure is idempotent.
226 // bool idempotent() { return true; }
227 bool apply_to_weak_ref_discovered_field() { return true; }
228 };