Tue, 05 May 2009 22:15:35 -0700
6833576: G1: assert illegal index, growableArray.hpp:186
Summary: The code that calculates the heap region index for an object address incorrectly used signed arithmetic.
Reviewed-by: jcoomes, ysr
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;
37 unsigned _conc_refine_traversals;
38 unsigned _conc_refine_cards;
40 size_t n_workers();
42 public:
43 G1RemSet(G1CollectedHeap* g1) :
44 _g1(g1), _conc_refine_traversals(0), _conc_refine_cards(0)
45 {}
47 // Invoke "blk->do_oop" on all pointers into the CS in object in regions
48 // outside the CS (having invoked "blk->set_region" to set the "from"
49 // region correctly beforehand.) The "worker_i" param is for the
50 // parallel case where the number of the worker thread calling this
51 // function can be helpful in partitioning the work to be done. It
52 // should be the same as the "i" passed to the calling thread's
53 // work(i) function. In the sequential case this param will be ingored.
54 virtual void oops_into_collection_set_do(OopsInHeapRegionClosure* blk,
55 int worker_i) = 0;
57 // Prepare for and cleanup after an oops_into_collection_set_do
58 // call. Must call each of these once before and after (in sequential
59 // code) any threads call oops into collection set do. (This offers an
60 // opportunity to sequential setup and teardown of structures needed by a
61 // parallel iteration over the CS's RS.)
62 virtual void prepare_for_oops_into_collection_set_do() = 0;
63 virtual void cleanup_after_oops_into_collection_set_do() = 0;
65 // If "this" is of the given subtype, return "this", else "NULL".
66 virtual HRInto_G1RemSet* as_HRInto_G1RemSet() { return NULL; }
68 // Record, if necessary, the fact that *p (where "p" is in region "from")
69 // has changed to its new value.
70 virtual void write_ref(HeapRegion* from, oop* p) = 0;
71 virtual void par_write_ref(HeapRegion* from, oop* p, int tid) = 0;
73 // Requires "region_bm" and "card_bm" to be bitmaps with 1 bit per region
74 // or card, respectively, such that a region or card with a corresponding
75 // 0 bit contains no part of any live object. Eliminates any remembered
76 // set entries that correspond to dead heap ranges.
77 virtual void scrub(BitMap* region_bm, BitMap* card_bm) = 0;
78 // Like the above, but assumes is called in parallel: "worker_num" is the
79 // parallel thread id of the current thread, and "claim_val" is the
80 // value that should be used to claim heap regions.
81 virtual void scrub_par(BitMap* region_bm, BitMap* card_bm,
82 int worker_num, int claim_val) = 0;
84 // Do any "refinement" activity that might be appropriate to the given
85 // G1RemSet. If "refinement" has iterateive "passes", do one pass.
86 // If "t" is non-NULL, it is the thread performing the refinement.
87 // Default implementation does nothing.
88 virtual void concurrentRefinementPass(ConcurrentG1Refine* cg1r) {}
90 // Refine the card corresponding to "card_ptr". If "sts" is non-NULL,
91 // join and leave around parts that must be atomic wrt GC. (NULL means
92 // being done at a safepoint.)
93 virtual void concurrentRefineOneCard(jbyte* card_ptr, int worker_i) {}
95 unsigned conc_refine_cards() { return _conc_refine_cards; }
97 // Print any relevant summary info.
98 virtual void print_summary_info() {}
100 // Prepare remebered set for verification.
101 virtual void prepare_for_verify() {};
102 };
105 // The simplest possible G1RemSet: iterates over all objects in non-CS
106 // regions, searching for pointers into the CS.
107 class StupidG1RemSet: public G1RemSet {
108 public:
109 StupidG1RemSet(G1CollectedHeap* g1) : G1RemSet(g1) {}
111 void oops_into_collection_set_do(OopsInHeapRegionClosure* blk,
112 int worker_i);
114 void prepare_for_oops_into_collection_set_do() {}
115 void cleanup_after_oops_into_collection_set_do() {}
117 // Nothing is necessary in the version below.
118 void write_ref(HeapRegion* from, oop* p) {}
119 void par_write_ref(HeapRegion* from, oop* p, int tid) {}
121 void scrub(BitMap* region_bm, BitMap* card_bm) {}
122 void scrub_par(BitMap* region_bm, BitMap* card_bm,
123 int worker_num, int claim_val) {}
125 };
127 // A G1RemSet in which each heap region has a rem set that records the
128 // external heap references into it. Uses a mod ref bs to track updates,
129 // so that they can be used to update the individual region remsets.
131 class HRInto_G1RemSet: public G1RemSet {
132 protected:
133 enum SomePrivateConstants {
134 UpdateRStoMergeSync = 0,
135 MergeRStoDoDirtySync = 1,
136 DoDirtySync = 2,
137 LastSync = 3,
139 SeqTask = 0,
140 NumSeqTasks = 1
141 };
143 CardTableModRefBS* _ct_bs;
144 SubTasksDone* _seq_task;
145 G1CollectorPolicy* _g1p;
147 ConcurrentG1Refine* _cg1r;
149 size_t* _cards_scanned;
150 size_t _total_cards_scanned;
152 // _par_traversal_in_progress is "true" iff a parallel traversal is in
153 // progress. If so, then cards added to remembered sets should also have
154 // their references into the collection summarized in "_new_refs".
155 bool _par_traversal_in_progress;
156 void set_par_traversal(bool b);
157 GrowableArray<oop*>** _new_refs;
158 void new_refs_iterate(OopClosure* cl);
160 public:
161 // This is called to reset dual hash tables after the gc pause
162 // is finished and the initial hash table is no longer being
163 // scanned.
164 void cleanupHRRS();
166 HRInto_G1RemSet(G1CollectedHeap* g1, CardTableModRefBS* ct_bs);
167 ~HRInto_G1RemSet();
169 void oops_into_collection_set_do(OopsInHeapRegionClosure* blk,
170 int worker_i);
172 void prepare_for_oops_into_collection_set_do();
173 void cleanup_after_oops_into_collection_set_do();
174 void scanRS(OopsInHeapRegionClosure* oc, int worker_i);
175 void scanNewRefsRS(OopsInHeapRegionClosure* oc, int worker_i);
176 void updateRS(int worker_i);
177 HeapRegion* calculateStartRegion(int i);
179 HRInto_G1RemSet* as_HRInto_G1RemSet() { return this; }
181 CardTableModRefBS* ct_bs() { return _ct_bs; }
182 size_t cardsScanned() { return _total_cards_scanned; }
184 // Record, if necessary, the fact that *p (where "p" is in region "from",
185 // which is required to be non-NULL) has changed to a new non-NULL value.
186 inline void write_ref(HeapRegion* from, oop* p);
187 // The "_nv" version is the same; it exists just so that it is not virtual.
188 inline void write_ref_nv(HeapRegion* from, oop* p);
190 inline bool self_forwarded(oop obj);
191 inline void par_write_ref(HeapRegion* from, oop* p, int tid);
193 void scrub(BitMap* region_bm, BitMap* card_bm);
194 void scrub_par(BitMap* region_bm, BitMap* card_bm,
195 int worker_num, int claim_val);
197 virtual void concurrentRefinementPass(ConcurrentG1Refine* t);
198 virtual void concurrentRefineOneCard(jbyte* card_ptr, int worker_i);
200 virtual void print_summary_info();
201 virtual void prepare_for_verify();
202 };
204 #define G1_REM_SET_LOGGING 0
206 class CountNonCleanMemRegionClosure: public MemRegionClosure {
207 G1CollectedHeap* _g1;
208 int _n;
209 HeapWord* _start_first;
210 public:
211 CountNonCleanMemRegionClosure(G1CollectedHeap* g1) :
212 _g1(g1), _n(0), _start_first(NULL)
213 {}
214 void do_MemRegion(MemRegion mr);
215 int n() { return _n; };
216 HeapWord* start_first() { return _start_first; }
217 };
219 class UpdateRSOopClosure: public OopClosure {
220 HeapRegion* _from;
221 HRInto_G1RemSet* _rs;
222 int _worker_i;
223 public:
224 UpdateRSOopClosure(HRInto_G1RemSet* rs, int worker_i = 0) :
225 _from(NULL), _rs(rs), _worker_i(worker_i) {
226 guarantee(_rs != NULL, "Requires an HRIntoG1RemSet");
227 }
229 void set_from(HeapRegion* from) {
230 assert(from != NULL, "from region must be non-NULL");
231 _from = from;
232 }
234 virtual void do_oop(narrowOop* p);
235 virtual void do_oop(oop* p);
237 // Override: this closure is idempotent.
238 // bool idempotent() { return true; }
239 bool apply_to_weak_ref_discovered_field() { return true; }
240 };