annotate src/share/vm/memory/cardTableRS.cpp @ 1091:6aa7255741f3

6906727: UseCompressedOops: some card-marking fixes related to object arrays Summary: Introduced a new write_ref_array(HeapWords* start, size_t count) method that does the requisite MemRegion range calculation so (some of the) clients of the erstwhile write_ref_array(MemRegion mr) do not need to worry. This removed all external uses of array_size(), which was also simplified and made private. Asserts were added to catch other possible issues. Further, less essential, fixes stemming from this investigation are deferred to CR 6904516 (to follow shortly in hs17). Reviewed-by: kvn, coleenp, jmasa
author ysr
date Thu, 03 Dec 2009 15:01:57 -0800
parents bd02caa94611
children c18cbe5936b8
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1 /*
844
bd02caa94611 6862919: Update copyright year
xdono
parents: 794
diff changeset
2 * Copyright 2001-2009 Sun Microsystems, Inc. All Rights Reserved.
0
a61af66fc99e Initial load
duke
parents:
diff changeset
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
a61af66fc99e Initial load
duke
parents:
diff changeset
4 *
a61af66fc99e Initial load
duke
parents:
diff changeset
5 * This code is free software; you can redistribute it and/or modify it
a61af66fc99e Initial load
duke
parents:
diff changeset
6 * under the terms of the GNU General Public License version 2 only, as
a61af66fc99e Initial load
duke
parents:
diff changeset
7 * published by the Free Software Foundation.
a61af66fc99e Initial load
duke
parents:
diff changeset
8 *
a61af66fc99e Initial load
duke
parents:
diff changeset
9 * This code is distributed in the hope that it will be useful, but WITHOUT
a61af66fc99e Initial load
duke
parents:
diff changeset
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
a61af66fc99e Initial load
duke
parents:
diff changeset
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
a61af66fc99e Initial load
duke
parents:
diff changeset
12 * version 2 for more details (a copy is included in the LICENSE file that
a61af66fc99e Initial load
duke
parents:
diff changeset
13 * accompanied this code).
a61af66fc99e Initial load
duke
parents:
diff changeset
14 *
a61af66fc99e Initial load
duke
parents:
diff changeset
15 * You should have received a copy of the GNU General Public License version
a61af66fc99e Initial load
duke
parents:
diff changeset
16 * 2 along with this work; if not, write to the Free Software Foundation,
a61af66fc99e Initial load
duke
parents:
diff changeset
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
a61af66fc99e Initial load
duke
parents:
diff changeset
18 *
a61af66fc99e Initial load
duke
parents:
diff changeset
19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
a61af66fc99e Initial load
duke
parents:
diff changeset
20 * CA 95054 USA or visit www.sun.com if you need additional information or
a61af66fc99e Initial load
duke
parents:
diff changeset
21 * have any questions.
a61af66fc99e Initial load
duke
parents:
diff changeset
22 *
a61af66fc99e Initial load
duke
parents:
diff changeset
23 */
a61af66fc99e Initial load
duke
parents:
diff changeset
24
a61af66fc99e Initial load
duke
parents:
diff changeset
25 # include "incls/_precompiled.incl"
a61af66fc99e Initial load
duke
parents:
diff changeset
26 # include "incls/_cardTableRS.cpp.incl"
a61af66fc99e Initial load
duke
parents:
diff changeset
27
a61af66fc99e Initial load
duke
parents:
diff changeset
28 CardTableRS::CardTableRS(MemRegion whole_heap,
a61af66fc99e Initial load
duke
parents:
diff changeset
29 int max_covered_regions) :
342
37f87013dfd8 6711316: Open source the Garbage-First garbage collector
ysr
parents: 113
diff changeset
30 GenRemSet(),
37f87013dfd8 6711316: Open source the Garbage-First garbage collector
ysr
parents: 113
diff changeset
31 _cur_youngergen_card_val(youngergenP1_card),
37f87013dfd8 6711316: Open source the Garbage-First garbage collector
ysr
parents: 113
diff changeset
32 _regions_to_iterate(max_covered_regions - 1)
0
a61af66fc99e Initial load
duke
parents:
diff changeset
33 {
342
37f87013dfd8 6711316: Open source the Garbage-First garbage collector
ysr
parents: 113
diff changeset
34 #ifndef SERIALGC
37f87013dfd8 6711316: Open source the Garbage-First garbage collector
ysr
parents: 113
diff changeset
35 if (UseG1GC) {
37f87013dfd8 6711316: Open source the Garbage-First garbage collector
ysr
parents: 113
diff changeset
36 _ct_bs = new G1SATBCardTableLoggingModRefBS(whole_heap,
37f87013dfd8 6711316: Open source the Garbage-First garbage collector
ysr
parents: 113
diff changeset
37 max_covered_regions);
37f87013dfd8 6711316: Open source the Garbage-First garbage collector
ysr
parents: 113
diff changeset
38 } else {
37f87013dfd8 6711316: Open source the Garbage-First garbage collector
ysr
parents: 113
diff changeset
39 _ct_bs = new CardTableModRefBSForCTRS(whole_heap, max_covered_regions);
37f87013dfd8 6711316: Open source the Garbage-First garbage collector
ysr
parents: 113
diff changeset
40 }
37f87013dfd8 6711316: Open source the Garbage-First garbage collector
ysr
parents: 113
diff changeset
41 #else
37f87013dfd8 6711316: Open source the Garbage-First garbage collector
ysr
parents: 113
diff changeset
42 _ct_bs = new CardTableModRefBSForCTRS(whole_heap, max_covered_regions);
37f87013dfd8 6711316: Open source the Garbage-First garbage collector
ysr
parents: 113
diff changeset
43 #endif
37f87013dfd8 6711316: Open source the Garbage-First garbage collector
ysr
parents: 113
diff changeset
44 set_bs(_ct_bs);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
45 _last_cur_val_in_gen = new jbyte[GenCollectedHeap::max_gens + 1];
a61af66fc99e Initial load
duke
parents:
diff changeset
46 if (_last_cur_val_in_gen == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
47 vm_exit_during_initialization("Could not last_cur_val_in_gen array.");
a61af66fc99e Initial load
duke
parents:
diff changeset
48 }
a61af66fc99e Initial load
duke
parents:
diff changeset
49 for (int i = 0; i < GenCollectedHeap::max_gens + 1; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
50 _last_cur_val_in_gen[i] = clean_card_val();
a61af66fc99e Initial load
duke
parents:
diff changeset
51 }
342
37f87013dfd8 6711316: Open source the Garbage-First garbage collector
ysr
parents: 113
diff changeset
52 _ct_bs->set_CTRS(this);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
53 }
a61af66fc99e Initial load
duke
parents:
diff changeset
54
a61af66fc99e Initial load
duke
parents:
diff changeset
55 void CardTableRS::resize_covered_region(MemRegion new_region) {
342
37f87013dfd8 6711316: Open source the Garbage-First garbage collector
ysr
parents: 113
diff changeset
56 _ct_bs->resize_covered_region(new_region);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
57 }
a61af66fc99e Initial load
duke
parents:
diff changeset
58
a61af66fc99e Initial load
duke
parents:
diff changeset
59 jbyte CardTableRS::find_unused_youngergenP_card_value() {
a61af66fc99e Initial load
duke
parents:
diff changeset
60 for (jbyte v = youngergenP1_card;
a61af66fc99e Initial load
duke
parents:
diff changeset
61 v < cur_youngergen_and_prev_nonclean_card;
a61af66fc99e Initial load
duke
parents:
diff changeset
62 v++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
63 bool seen = false;
342
37f87013dfd8 6711316: Open source the Garbage-First garbage collector
ysr
parents: 113
diff changeset
64 for (int g = 0; g < _regions_to_iterate; g++) {
0
a61af66fc99e Initial load
duke
parents:
diff changeset
65 if (_last_cur_val_in_gen[g] == v) {
a61af66fc99e Initial load
duke
parents:
diff changeset
66 seen = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
67 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
68 }
a61af66fc99e Initial load
duke
parents:
diff changeset
69 }
a61af66fc99e Initial load
duke
parents:
diff changeset
70 if (!seen) return v;
a61af66fc99e Initial load
duke
parents:
diff changeset
71 }
a61af66fc99e Initial load
duke
parents:
diff changeset
72 ShouldNotReachHere();
a61af66fc99e Initial load
duke
parents:
diff changeset
73 return 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
74 }
a61af66fc99e Initial load
duke
parents:
diff changeset
75
a61af66fc99e Initial load
duke
parents:
diff changeset
76 void CardTableRS::prepare_for_younger_refs_iterate(bool parallel) {
a61af66fc99e Initial load
duke
parents:
diff changeset
77 // Parallel or sequential, we must always set the prev to equal the
a61af66fc99e Initial load
duke
parents:
diff changeset
78 // last one written.
a61af66fc99e Initial load
duke
parents:
diff changeset
79 if (parallel) {
a61af66fc99e Initial load
duke
parents:
diff changeset
80 // Find a parallel value to be used next.
a61af66fc99e Initial load
duke
parents:
diff changeset
81 jbyte next_val = find_unused_youngergenP_card_value();
a61af66fc99e Initial load
duke
parents:
diff changeset
82 set_cur_youngergen_card_val(next_val);
a61af66fc99e Initial load
duke
parents:
diff changeset
83
a61af66fc99e Initial load
duke
parents:
diff changeset
84 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
85 // In an sequential traversal we will always write youngergen, so that
a61af66fc99e Initial load
duke
parents:
diff changeset
86 // the inline barrier is correct.
a61af66fc99e Initial load
duke
parents:
diff changeset
87 set_cur_youngergen_card_val(youngergen_card);
a61af66fc99e Initial load
duke
parents:
diff changeset
88 }
a61af66fc99e Initial load
duke
parents:
diff changeset
89 }
a61af66fc99e Initial load
duke
parents:
diff changeset
90
a61af66fc99e Initial load
duke
parents:
diff changeset
91 void CardTableRS::younger_refs_iterate(Generation* g,
a61af66fc99e Initial load
duke
parents:
diff changeset
92 OopsInGenClosure* blk) {
a61af66fc99e Initial load
duke
parents:
diff changeset
93 _last_cur_val_in_gen[g->level()+1] = cur_youngergen_card_val();
a61af66fc99e Initial load
duke
parents:
diff changeset
94 g->younger_refs_iterate(blk);
a61af66fc99e Initial load
duke
parents:
diff changeset
95 }
a61af66fc99e Initial load
duke
parents:
diff changeset
96
a61af66fc99e Initial load
duke
parents:
diff changeset
97 class ClearNoncleanCardWrapper: public MemRegionClosure {
a61af66fc99e Initial load
duke
parents:
diff changeset
98 MemRegionClosure* _dirty_card_closure;
a61af66fc99e Initial load
duke
parents:
diff changeset
99 CardTableRS* _ct;
a61af66fc99e Initial load
duke
parents:
diff changeset
100 bool _is_par;
a61af66fc99e Initial load
duke
parents:
diff changeset
101 private:
a61af66fc99e Initial load
duke
parents:
diff changeset
102 // Clears the given card, return true if the corresponding card should be
a61af66fc99e Initial load
duke
parents:
diff changeset
103 // processed.
a61af66fc99e Initial load
duke
parents:
diff changeset
104 bool clear_card(jbyte* entry) {
a61af66fc99e Initial load
duke
parents:
diff changeset
105 if (_is_par) {
a61af66fc99e Initial load
duke
parents:
diff changeset
106 while (true) {
a61af66fc99e Initial load
duke
parents:
diff changeset
107 // In the parallel case, we may have to do this several times.
a61af66fc99e Initial load
duke
parents:
diff changeset
108 jbyte entry_val = *entry;
a61af66fc99e Initial load
duke
parents:
diff changeset
109 assert(entry_val != CardTableRS::clean_card_val(),
a61af66fc99e Initial load
duke
parents:
diff changeset
110 "We shouldn't be looking at clean cards, and this should "
a61af66fc99e Initial load
duke
parents:
diff changeset
111 "be the only place they get cleaned.");
a61af66fc99e Initial load
duke
parents:
diff changeset
112 if (CardTableRS::card_is_dirty_wrt_gen_iter(entry_val)
a61af66fc99e Initial load
duke
parents:
diff changeset
113 || _ct->is_prev_youngergen_card_val(entry_val)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
114 jbyte res =
a61af66fc99e Initial load
duke
parents:
diff changeset
115 Atomic::cmpxchg(CardTableRS::clean_card_val(), entry, entry_val);
a61af66fc99e Initial load
duke
parents:
diff changeset
116 if (res == entry_val) {
a61af66fc99e Initial load
duke
parents:
diff changeset
117 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
118 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
119 assert(res == CardTableRS::cur_youngergen_and_prev_nonclean_card,
a61af66fc99e Initial load
duke
parents:
diff changeset
120 "The CAS above should only fail if another thread did "
a61af66fc99e Initial load
duke
parents:
diff changeset
121 "a GC write barrier.");
a61af66fc99e Initial load
duke
parents:
diff changeset
122 }
a61af66fc99e Initial load
duke
parents:
diff changeset
123 } else if (entry_val ==
a61af66fc99e Initial load
duke
parents:
diff changeset
124 CardTableRS::cur_youngergen_and_prev_nonclean_card) {
a61af66fc99e Initial load
duke
parents:
diff changeset
125 // Parallelism shouldn't matter in this case. Only the thread
a61af66fc99e Initial load
duke
parents:
diff changeset
126 // assigned to scan the card should change this value.
a61af66fc99e Initial load
duke
parents:
diff changeset
127 *entry = _ct->cur_youngergen_card_val();
a61af66fc99e Initial load
duke
parents:
diff changeset
128 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
129 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
130 assert(entry_val == _ct->cur_youngergen_card_val(),
a61af66fc99e Initial load
duke
parents:
diff changeset
131 "Should be the only possibility.");
a61af66fc99e Initial load
duke
parents:
diff changeset
132 // In this case, the card was clean before, and become
a61af66fc99e Initial load
duke
parents:
diff changeset
133 // cur_youngergen only because of processing of a promoted object.
a61af66fc99e Initial load
duke
parents:
diff changeset
134 // We don't have to look at the card.
a61af66fc99e Initial load
duke
parents:
diff changeset
135 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
136 }
a61af66fc99e Initial load
duke
parents:
diff changeset
137 }
a61af66fc99e Initial load
duke
parents:
diff changeset
138 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
139 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
140 jbyte entry_val = *entry;
a61af66fc99e Initial load
duke
parents:
diff changeset
141 assert(entry_val != CardTableRS::clean_card_val(),
a61af66fc99e Initial load
duke
parents:
diff changeset
142 "We shouldn't be looking at clean cards, and this should "
a61af66fc99e Initial load
duke
parents:
diff changeset
143 "be the only place they get cleaned.");
a61af66fc99e Initial load
duke
parents:
diff changeset
144 assert(entry_val != CardTableRS::cur_youngergen_and_prev_nonclean_card,
a61af66fc99e Initial load
duke
parents:
diff changeset
145 "This should be possible in the sequential case.");
a61af66fc99e Initial load
duke
parents:
diff changeset
146 *entry = CardTableRS::clean_card_val();
a61af66fc99e Initial load
duke
parents:
diff changeset
147 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
148 }
a61af66fc99e Initial load
duke
parents:
diff changeset
149 }
a61af66fc99e Initial load
duke
parents:
diff changeset
150
a61af66fc99e Initial load
duke
parents:
diff changeset
151 public:
a61af66fc99e Initial load
duke
parents:
diff changeset
152 ClearNoncleanCardWrapper(MemRegionClosure* dirty_card_closure,
a61af66fc99e Initial load
duke
parents:
diff changeset
153 CardTableRS* ct) :
a61af66fc99e Initial load
duke
parents:
diff changeset
154 _dirty_card_closure(dirty_card_closure), _ct(ct) {
a61af66fc99e Initial load
duke
parents:
diff changeset
155 _is_par = (SharedHeap::heap()->n_par_threads() > 0);
a61af66fc99e Initial load
duke
parents:
diff changeset
156 }
a61af66fc99e Initial load
duke
parents:
diff changeset
157 void do_MemRegion(MemRegion mr) {
a61af66fc99e Initial load
duke
parents:
diff changeset
158 // We start at the high end of "mr", walking backwards
a61af66fc99e Initial load
duke
parents:
diff changeset
159 // while accumulating a contiguous dirty range of cards in
a61af66fc99e Initial load
duke
parents:
diff changeset
160 // [start_of_non_clean, end_of_non_clean) which we then
a61af66fc99e Initial load
duke
parents:
diff changeset
161 // process en masse.
a61af66fc99e Initial load
duke
parents:
diff changeset
162 HeapWord* end_of_non_clean = mr.end();
a61af66fc99e Initial load
duke
parents:
diff changeset
163 HeapWord* start_of_non_clean = end_of_non_clean;
a61af66fc99e Initial load
duke
parents:
diff changeset
164 jbyte* entry = _ct->byte_for(mr.last());
a61af66fc99e Initial load
duke
parents:
diff changeset
165 const jbyte* first_entry = _ct->byte_for(mr.start());
a61af66fc99e Initial load
duke
parents:
diff changeset
166 while (entry >= first_entry) {
a61af66fc99e Initial load
duke
parents:
diff changeset
167 HeapWord* cur = _ct->addr_for(entry);
a61af66fc99e Initial load
duke
parents:
diff changeset
168 if (!clear_card(entry)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
169 // We hit a clean card; process any non-empty
a61af66fc99e Initial load
duke
parents:
diff changeset
170 // dirty range accumulated so far.
a61af66fc99e Initial load
duke
parents:
diff changeset
171 if (start_of_non_clean < end_of_non_clean) {
a61af66fc99e Initial load
duke
parents:
diff changeset
172 MemRegion mr2(start_of_non_clean, end_of_non_clean);
a61af66fc99e Initial load
duke
parents:
diff changeset
173 _dirty_card_closure->do_MemRegion(mr2);
a61af66fc99e Initial load
duke
parents:
diff changeset
174 }
a61af66fc99e Initial load
duke
parents:
diff changeset
175 // Reset the dirty window while continuing to
a61af66fc99e Initial load
duke
parents:
diff changeset
176 // look for the next dirty window to process.
a61af66fc99e Initial load
duke
parents:
diff changeset
177 end_of_non_clean = cur;
a61af66fc99e Initial load
duke
parents:
diff changeset
178 start_of_non_clean = end_of_non_clean;
a61af66fc99e Initial load
duke
parents:
diff changeset
179 }
a61af66fc99e Initial load
duke
parents:
diff changeset
180 // Open the left end of the window one card to the left.
a61af66fc99e Initial load
duke
parents:
diff changeset
181 start_of_non_clean = cur;
a61af66fc99e Initial load
duke
parents:
diff changeset
182 // Note that "entry" leads "start_of_non_clean" in
a61af66fc99e Initial load
duke
parents:
diff changeset
183 // its leftward excursion after this point
a61af66fc99e Initial load
duke
parents:
diff changeset
184 // in the loop and, when we hit the left end of "mr",
a61af66fc99e Initial load
duke
parents:
diff changeset
185 // will point off of the left end of the card-table
a61af66fc99e Initial load
duke
parents:
diff changeset
186 // for "mr".
a61af66fc99e Initial load
duke
parents:
diff changeset
187 entry--;
a61af66fc99e Initial load
duke
parents:
diff changeset
188 }
a61af66fc99e Initial load
duke
parents:
diff changeset
189 // If the first card of "mr" was dirty, we will have
a61af66fc99e Initial load
duke
parents:
diff changeset
190 // been left with a dirty window, co-initial with "mr",
a61af66fc99e Initial load
duke
parents:
diff changeset
191 // which we now process.
a61af66fc99e Initial load
duke
parents:
diff changeset
192 if (start_of_non_clean < end_of_non_clean) {
a61af66fc99e Initial load
duke
parents:
diff changeset
193 MemRegion mr2(start_of_non_clean, end_of_non_clean);
a61af66fc99e Initial load
duke
parents:
diff changeset
194 _dirty_card_closure->do_MemRegion(mr2);
a61af66fc99e Initial load
duke
parents:
diff changeset
195 }
a61af66fc99e Initial load
duke
parents:
diff changeset
196 }
a61af66fc99e Initial load
duke
parents:
diff changeset
197 };
a61af66fc99e Initial load
duke
parents:
diff changeset
198 // clean (by dirty->clean before) ==> cur_younger_gen
a61af66fc99e Initial load
duke
parents:
diff changeset
199 // dirty ==> cur_youngergen_and_prev_nonclean_card
a61af66fc99e Initial load
duke
parents:
diff changeset
200 // precleaned ==> cur_youngergen_and_prev_nonclean_card
a61af66fc99e Initial load
duke
parents:
diff changeset
201 // prev-younger-gen ==> cur_youngergen_and_prev_nonclean_card
a61af66fc99e Initial load
duke
parents:
diff changeset
202 // cur-younger-gen ==> cur_younger_gen
a61af66fc99e Initial load
duke
parents:
diff changeset
203 // cur_youngergen_and_prev_nonclean_card ==> no change.
113
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 6
diff changeset
204 void CardTableRS::write_ref_field_gc_par(void* field, oop new_val) {
0
a61af66fc99e Initial load
duke
parents:
diff changeset
205 jbyte* entry = ct_bs()->byte_for(field);
a61af66fc99e Initial load
duke
parents:
diff changeset
206 do {
a61af66fc99e Initial load
duke
parents:
diff changeset
207 jbyte entry_val = *entry;
a61af66fc99e Initial load
duke
parents:
diff changeset
208 // We put this first because it's probably the most common case.
a61af66fc99e Initial load
duke
parents:
diff changeset
209 if (entry_val == clean_card_val()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
210 // No threat of contention with cleaning threads.
a61af66fc99e Initial load
duke
parents:
diff changeset
211 *entry = cur_youngergen_card_val();
a61af66fc99e Initial load
duke
parents:
diff changeset
212 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
213 } else if (card_is_dirty_wrt_gen_iter(entry_val)
a61af66fc99e Initial load
duke
parents:
diff changeset
214 || is_prev_youngergen_card_val(entry_val)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
215 // Mark it as both cur and prev youngergen; card cleaning thread will
a61af66fc99e Initial load
duke
parents:
diff changeset
216 // eventually remove the previous stuff.
a61af66fc99e Initial load
duke
parents:
diff changeset
217 jbyte new_val = cur_youngergen_and_prev_nonclean_card;
a61af66fc99e Initial load
duke
parents:
diff changeset
218 jbyte res = Atomic::cmpxchg(new_val, entry, entry_val);
a61af66fc99e Initial load
duke
parents:
diff changeset
219 // Did the CAS succeed?
a61af66fc99e Initial load
duke
parents:
diff changeset
220 if (res == entry_val) return;
a61af66fc99e Initial load
duke
parents:
diff changeset
221 // Otherwise, retry, to see the new value.
a61af66fc99e Initial load
duke
parents:
diff changeset
222 continue;
a61af66fc99e Initial load
duke
parents:
diff changeset
223 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
224 assert(entry_val == cur_youngergen_and_prev_nonclean_card
a61af66fc99e Initial load
duke
parents:
diff changeset
225 || entry_val == cur_youngergen_card_val(),
a61af66fc99e Initial load
duke
parents:
diff changeset
226 "should be only possibilities.");
a61af66fc99e Initial load
duke
parents:
diff changeset
227 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
228 }
a61af66fc99e Initial load
duke
parents:
diff changeset
229 } while (true);
a61af66fc99e Initial load
duke
parents:
diff changeset
230 }
a61af66fc99e Initial load
duke
parents:
diff changeset
231
a61af66fc99e Initial load
duke
parents:
diff changeset
232 void CardTableRS::younger_refs_in_space_iterate(Space* sp,
a61af66fc99e Initial load
duke
parents:
diff changeset
233 OopsInGenClosure* cl) {
342
37f87013dfd8 6711316: Open source the Garbage-First garbage collector
ysr
parents: 113
diff changeset
234 DirtyCardToOopClosure* dcto_cl = sp->new_dcto_cl(cl, _ct_bs->precision(),
0
a61af66fc99e Initial load
duke
parents:
diff changeset
235 cl->gen_boundary());
a61af66fc99e Initial load
duke
parents:
diff changeset
236 ClearNoncleanCardWrapper clear_cl(dcto_cl, this);
a61af66fc99e Initial load
duke
parents:
diff changeset
237
342
37f87013dfd8 6711316: Open source the Garbage-First garbage collector
ysr
parents: 113
diff changeset
238 _ct_bs->non_clean_card_iterate(sp, sp->used_region_at_save_marks(),
0
a61af66fc99e Initial load
duke
parents:
diff changeset
239 dcto_cl, &clear_cl, false);
a61af66fc99e Initial load
duke
parents:
diff changeset
240 }
a61af66fc99e Initial load
duke
parents:
diff changeset
241
a61af66fc99e Initial load
duke
parents:
diff changeset
242 void CardTableRS::clear_into_younger(Generation* gen, bool clear_perm) {
a61af66fc99e Initial load
duke
parents:
diff changeset
243 GenCollectedHeap* gch = GenCollectedHeap::heap();
a61af66fc99e Initial load
duke
parents:
diff changeset
244 // Generations younger than gen have been evacuated. We can clear
a61af66fc99e Initial load
duke
parents:
diff changeset
245 // card table entries for gen (we know that it has no pointers
a61af66fc99e Initial load
duke
parents:
diff changeset
246 // to younger gens) and for those below. The card tables for
a61af66fc99e Initial load
duke
parents:
diff changeset
247 // the youngest gen need never be cleared, and those for perm gen
a61af66fc99e Initial load
duke
parents:
diff changeset
248 // will be cleared based on the parameter clear_perm.
a61af66fc99e Initial load
duke
parents:
diff changeset
249 // There's a bit of subtlety in the clear() and invalidate()
a61af66fc99e Initial load
duke
parents:
diff changeset
250 // methods that we exploit here and in invalidate_or_clear()
a61af66fc99e Initial load
duke
parents:
diff changeset
251 // below to avoid missing cards at the fringes. If clear() or
a61af66fc99e Initial load
duke
parents:
diff changeset
252 // invalidate() are changed in the future, this code should
a61af66fc99e Initial load
duke
parents:
diff changeset
253 // be revisited. 20040107.ysr
a61af66fc99e Initial load
duke
parents:
diff changeset
254 Generation* g = gen;
a61af66fc99e Initial load
duke
parents:
diff changeset
255 for(Generation* prev_gen = gch->prev_gen(g);
a61af66fc99e Initial load
duke
parents:
diff changeset
256 prev_gen != NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
257 g = prev_gen, prev_gen = gch->prev_gen(g)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
258 MemRegion to_be_cleared_mr = g->prev_used_region();
a61af66fc99e Initial load
duke
parents:
diff changeset
259 clear(to_be_cleared_mr);
a61af66fc99e Initial load
duke
parents:
diff changeset
260 }
a61af66fc99e Initial load
duke
parents:
diff changeset
261 // Clear perm gen cards if asked to do so.
a61af66fc99e Initial load
duke
parents:
diff changeset
262 if (clear_perm) {
a61af66fc99e Initial load
duke
parents:
diff changeset
263 MemRegion to_be_cleared_mr = gch->perm_gen()->prev_used_region();
a61af66fc99e Initial load
duke
parents:
diff changeset
264 clear(to_be_cleared_mr);
a61af66fc99e Initial load
duke
parents:
diff changeset
265 }
a61af66fc99e Initial load
duke
parents:
diff changeset
266 }
a61af66fc99e Initial load
duke
parents:
diff changeset
267
a61af66fc99e Initial load
duke
parents:
diff changeset
268 void CardTableRS::invalidate_or_clear(Generation* gen, bool younger,
a61af66fc99e Initial load
duke
parents:
diff changeset
269 bool perm) {
a61af66fc99e Initial load
duke
parents:
diff changeset
270 GenCollectedHeap* gch = GenCollectedHeap::heap();
a61af66fc99e Initial load
duke
parents:
diff changeset
271 // For each generation gen (and younger and/or perm)
a61af66fc99e Initial load
duke
parents:
diff changeset
272 // invalidate the cards for the currently occupied part
a61af66fc99e Initial load
duke
parents:
diff changeset
273 // of that generation and clear the cards for the
a61af66fc99e Initial load
duke
parents:
diff changeset
274 // unoccupied part of the generation (if any, making use
a61af66fc99e Initial load
duke
parents:
diff changeset
275 // of that generation's prev_used_region to determine that
a61af66fc99e Initial load
duke
parents:
diff changeset
276 // region). No need to do anything for the youngest
a61af66fc99e Initial load
duke
parents:
diff changeset
277 // generation. Also see note#20040107.ysr above.
a61af66fc99e Initial load
duke
parents:
diff changeset
278 Generation* g = gen;
a61af66fc99e Initial load
duke
parents:
diff changeset
279 for(Generation* prev_gen = gch->prev_gen(g); prev_gen != NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
280 g = prev_gen, prev_gen = gch->prev_gen(g)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
281 MemRegion used_mr = g->used_region();
a61af66fc99e Initial load
duke
parents:
diff changeset
282 MemRegion to_be_cleared_mr = g->prev_used_region().minus(used_mr);
a61af66fc99e Initial load
duke
parents:
diff changeset
283 if (!to_be_cleared_mr.is_empty()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
284 clear(to_be_cleared_mr);
a61af66fc99e Initial load
duke
parents:
diff changeset
285 }
a61af66fc99e Initial load
duke
parents:
diff changeset
286 invalidate(used_mr);
a61af66fc99e Initial load
duke
parents:
diff changeset
287 if (!younger) break;
a61af66fc99e Initial load
duke
parents:
diff changeset
288 }
a61af66fc99e Initial load
duke
parents:
diff changeset
289 // Clear perm gen cards if asked to do so.
a61af66fc99e Initial load
duke
parents:
diff changeset
290 if (perm) {
a61af66fc99e Initial load
duke
parents:
diff changeset
291 g = gch->perm_gen();
a61af66fc99e Initial load
duke
parents:
diff changeset
292 MemRegion used_mr = g->used_region();
a61af66fc99e Initial load
duke
parents:
diff changeset
293 MemRegion to_be_cleared_mr = g->prev_used_region().minus(used_mr);
a61af66fc99e Initial load
duke
parents:
diff changeset
294 if (!to_be_cleared_mr.is_empty()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
295 clear(to_be_cleared_mr);
a61af66fc99e Initial load
duke
parents:
diff changeset
296 }
a61af66fc99e Initial load
duke
parents:
diff changeset
297 invalidate(used_mr);
a61af66fc99e Initial load
duke
parents:
diff changeset
298 }
a61af66fc99e Initial load
duke
parents:
diff changeset
299 }
a61af66fc99e Initial load
duke
parents:
diff changeset
300
a61af66fc99e Initial load
duke
parents:
diff changeset
301
a61af66fc99e Initial load
duke
parents:
diff changeset
302 class VerifyCleanCardClosure: public OopClosure {
113
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 6
diff changeset
303 private:
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 6
diff changeset
304 HeapWord* _boundary;
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 6
diff changeset
305 HeapWord* _begin;
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 6
diff changeset
306 HeapWord* _end;
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 6
diff changeset
307 protected:
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 6
diff changeset
308 template <class T> void do_oop_work(T* p) {
0
a61af66fc99e Initial load
duke
parents:
diff changeset
309 HeapWord* jp = (HeapWord*)p;
113
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 6
diff changeset
310 if (jp >= _begin && jp < _end) {
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 6
diff changeset
311 oop obj = oopDesc::load_decode_heap_oop(p);
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 6
diff changeset
312 guarantee(obj == NULL ||
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 6
diff changeset
313 (HeapWord*)p < _boundary ||
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 6
diff changeset
314 (HeapWord*)obj >= _boundary,
0
a61af66fc99e Initial load
duke
parents:
diff changeset
315 "pointer on clean card crosses boundary");
a61af66fc99e Initial load
duke
parents:
diff changeset
316 }
a61af66fc99e Initial load
duke
parents:
diff changeset
317 }
113
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 6
diff changeset
318 public:
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 6
diff changeset
319 VerifyCleanCardClosure(HeapWord* b, HeapWord* begin, HeapWord* end) :
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 6
diff changeset
320 _boundary(b), _begin(begin), _end(end) {}
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 6
diff changeset
321 virtual void do_oop(oop* p) { VerifyCleanCardClosure::do_oop_work(p); }
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 6
diff changeset
322 virtual void do_oop(narrowOop* p) { VerifyCleanCardClosure::do_oop_work(p); }
0
a61af66fc99e Initial load
duke
parents:
diff changeset
323 };
a61af66fc99e Initial load
duke
parents:
diff changeset
324
a61af66fc99e Initial load
duke
parents:
diff changeset
325 class VerifyCTSpaceClosure: public SpaceClosure {
113
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 6
diff changeset
326 private:
0
a61af66fc99e Initial load
duke
parents:
diff changeset
327 CardTableRS* _ct;
a61af66fc99e Initial load
duke
parents:
diff changeset
328 HeapWord* _boundary;
a61af66fc99e Initial load
duke
parents:
diff changeset
329 public:
a61af66fc99e Initial load
duke
parents:
diff changeset
330 VerifyCTSpaceClosure(CardTableRS* ct, HeapWord* boundary) :
a61af66fc99e Initial load
duke
parents:
diff changeset
331 _ct(ct), _boundary(boundary) {}
113
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 6
diff changeset
332 virtual void do_space(Space* s) { _ct->verify_space(s, _boundary); }
0
a61af66fc99e Initial load
duke
parents:
diff changeset
333 };
a61af66fc99e Initial load
duke
parents:
diff changeset
334
a61af66fc99e Initial load
duke
parents:
diff changeset
335 class VerifyCTGenClosure: public GenCollectedHeap::GenClosure {
a61af66fc99e Initial load
duke
parents:
diff changeset
336 CardTableRS* _ct;
a61af66fc99e Initial load
duke
parents:
diff changeset
337 public:
a61af66fc99e Initial load
duke
parents:
diff changeset
338 VerifyCTGenClosure(CardTableRS* ct) : _ct(ct) {}
a61af66fc99e Initial load
duke
parents:
diff changeset
339 void do_generation(Generation* gen) {
a61af66fc99e Initial load
duke
parents:
diff changeset
340 // Skip the youngest generation.
a61af66fc99e Initial load
duke
parents:
diff changeset
341 if (gen->level() == 0) return;
a61af66fc99e Initial load
duke
parents:
diff changeset
342 // Normally, we're interested in pointers to younger generations.
a61af66fc99e Initial load
duke
parents:
diff changeset
343 VerifyCTSpaceClosure blk(_ct, gen->reserved().start());
a61af66fc99e Initial load
duke
parents:
diff changeset
344 gen->space_iterate(&blk, true);
a61af66fc99e Initial load
duke
parents:
diff changeset
345 }
a61af66fc99e Initial load
duke
parents:
diff changeset
346 };
a61af66fc99e Initial load
duke
parents:
diff changeset
347
a61af66fc99e Initial load
duke
parents:
diff changeset
348 void CardTableRS::verify_space(Space* s, HeapWord* gen_boundary) {
a61af66fc99e Initial load
duke
parents:
diff changeset
349 // We don't need to do young-gen spaces.
a61af66fc99e Initial load
duke
parents:
diff changeset
350 if (s->end() <= gen_boundary) return;
a61af66fc99e Initial load
duke
parents:
diff changeset
351 MemRegion used = s->used_region();
a61af66fc99e Initial load
duke
parents:
diff changeset
352
a61af66fc99e Initial load
duke
parents:
diff changeset
353 jbyte* cur_entry = byte_for(used.start());
a61af66fc99e Initial load
duke
parents:
diff changeset
354 jbyte* limit = byte_after(used.last());
a61af66fc99e Initial load
duke
parents:
diff changeset
355 while (cur_entry < limit) {
a61af66fc99e Initial load
duke
parents:
diff changeset
356 if (*cur_entry == CardTableModRefBS::clean_card) {
a61af66fc99e Initial load
duke
parents:
diff changeset
357 jbyte* first_dirty = cur_entry+1;
a61af66fc99e Initial load
duke
parents:
diff changeset
358 while (first_dirty < limit &&
a61af66fc99e Initial load
duke
parents:
diff changeset
359 *first_dirty == CardTableModRefBS::clean_card) {
a61af66fc99e Initial load
duke
parents:
diff changeset
360 first_dirty++;
a61af66fc99e Initial load
duke
parents:
diff changeset
361 }
a61af66fc99e Initial load
duke
parents:
diff changeset
362 // If the first object is a regular object, and it has a
a61af66fc99e Initial load
duke
parents:
diff changeset
363 // young-to-old field, that would mark the previous card.
a61af66fc99e Initial load
duke
parents:
diff changeset
364 HeapWord* boundary = addr_for(cur_entry);
a61af66fc99e Initial load
duke
parents:
diff changeset
365 HeapWord* end = (first_dirty >= limit) ? used.end() : addr_for(first_dirty);
a61af66fc99e Initial load
duke
parents:
diff changeset
366 HeapWord* boundary_block = s->block_start(boundary);
a61af66fc99e Initial load
duke
parents:
diff changeset
367 HeapWord* begin = boundary; // Until proven otherwise.
a61af66fc99e Initial load
duke
parents:
diff changeset
368 HeapWord* start_block = boundary_block; // Until proven otherwise.
a61af66fc99e Initial load
duke
parents:
diff changeset
369 if (boundary_block < boundary) {
a61af66fc99e Initial load
duke
parents:
diff changeset
370 if (s->block_is_obj(boundary_block) && s->obj_is_alive(boundary_block)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
371 oop boundary_obj = oop(boundary_block);
a61af66fc99e Initial load
duke
parents:
diff changeset
372 if (!boundary_obj->is_objArray() &&
a61af66fc99e Initial load
duke
parents:
diff changeset
373 !boundary_obj->is_typeArray()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
374 guarantee(cur_entry > byte_for(used.start()),
a61af66fc99e Initial load
duke
parents:
diff changeset
375 "else boundary would be boundary_block");
a61af66fc99e Initial load
duke
parents:
diff changeset
376 if (*byte_for(boundary_block) != CardTableModRefBS::clean_card) {
a61af66fc99e Initial load
duke
parents:
diff changeset
377 begin = boundary_block + s->block_size(boundary_block);
a61af66fc99e Initial load
duke
parents:
diff changeset
378 start_block = begin;
a61af66fc99e Initial load
duke
parents:
diff changeset
379 }
a61af66fc99e Initial load
duke
parents:
diff changeset
380 }
a61af66fc99e Initial load
duke
parents:
diff changeset
381 }
a61af66fc99e Initial load
duke
parents:
diff changeset
382 }
a61af66fc99e Initial load
duke
parents:
diff changeset
383 // Now traverse objects until end.
a61af66fc99e Initial load
duke
parents:
diff changeset
384 HeapWord* cur = start_block;
a61af66fc99e Initial load
duke
parents:
diff changeset
385 VerifyCleanCardClosure verify_blk(gen_boundary, begin, end);
a61af66fc99e Initial load
duke
parents:
diff changeset
386 while (cur < end) {
a61af66fc99e Initial load
duke
parents:
diff changeset
387 if (s->block_is_obj(cur) && s->obj_is_alive(cur)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
388 oop(cur)->oop_iterate(&verify_blk);
a61af66fc99e Initial load
duke
parents:
diff changeset
389 }
a61af66fc99e Initial load
duke
parents:
diff changeset
390 cur += s->block_size(cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
391 }
a61af66fc99e Initial load
duke
parents:
diff changeset
392 cur_entry = first_dirty;
a61af66fc99e Initial load
duke
parents:
diff changeset
393 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
394 // We'd normally expect that cur_youngergen_and_prev_nonclean_card
a61af66fc99e Initial load
duke
parents:
diff changeset
395 // is a transient value, that cannot be in the card table
a61af66fc99e Initial load
duke
parents:
diff changeset
396 // except during GC, and thus assert that:
a61af66fc99e Initial load
duke
parents:
diff changeset
397 // guarantee(*cur_entry != cur_youngergen_and_prev_nonclean_card,
a61af66fc99e Initial load
duke
parents:
diff changeset
398 // "Illegal CT value");
a61af66fc99e Initial load
duke
parents:
diff changeset
399 // That however, need not hold, as will become clear in the
a61af66fc99e Initial load
duke
parents:
diff changeset
400 // following...
a61af66fc99e Initial load
duke
parents:
diff changeset
401
a61af66fc99e Initial load
duke
parents:
diff changeset
402 // We'd normally expect that if we are in the parallel case,
a61af66fc99e Initial load
duke
parents:
diff changeset
403 // we can't have left a prev value (which would be different
a61af66fc99e Initial load
duke
parents:
diff changeset
404 // from the current value) in the card table, and so we'd like to
a61af66fc99e Initial load
duke
parents:
diff changeset
405 // assert that:
a61af66fc99e Initial load
duke
parents:
diff changeset
406 // guarantee(cur_youngergen_card_val() == youngergen_card
a61af66fc99e Initial load
duke
parents:
diff changeset
407 // || !is_prev_youngergen_card_val(*cur_entry),
a61af66fc99e Initial load
duke
parents:
diff changeset
408 // "Illegal CT value");
a61af66fc99e Initial load
duke
parents:
diff changeset
409 // That, however, may not hold occasionally, because of
a61af66fc99e Initial load
duke
parents:
diff changeset
410 // CMS or MSC in the old gen. To wit, consider the
a61af66fc99e Initial load
duke
parents:
diff changeset
411 // following two simple illustrative scenarios:
a61af66fc99e Initial load
duke
parents:
diff changeset
412 // (a) CMS: Consider the case where a large object L
a61af66fc99e Initial load
duke
parents:
diff changeset
413 // spanning several cards is allocated in the old
a61af66fc99e Initial load
duke
parents:
diff changeset
414 // gen, and has a young gen reference stored in it, dirtying
a61af66fc99e Initial load
duke
parents:
diff changeset
415 // some interior cards. A young collection scans the card,
a61af66fc99e Initial load
duke
parents:
diff changeset
416 // finds a young ref and installs a youngergenP_n value.
a61af66fc99e Initial load
duke
parents:
diff changeset
417 // L then goes dead. Now a CMS collection starts,
a61af66fc99e Initial load
duke
parents:
diff changeset
418 // finds L dead and sweeps it up. Assume that L is
a61af66fc99e Initial load
duke
parents:
diff changeset
419 // abutting _unallocated_blk, so _unallocated_blk is
a61af66fc99e Initial load
duke
parents:
diff changeset
420 // adjusted down to (below) L. Assume further that
a61af66fc99e Initial load
duke
parents:
diff changeset
421 // no young collection intervenes during this CMS cycle.
a61af66fc99e Initial load
duke
parents:
diff changeset
422 // The next young gen cycle will not get to look at this
a61af66fc99e Initial load
duke
parents:
diff changeset
423 // youngergenP_n card since it lies in the unoccupied
a61af66fc99e Initial load
duke
parents:
diff changeset
424 // part of the space.
a61af66fc99e Initial load
duke
parents:
diff changeset
425 // Some young collections later the blocks on this
a61af66fc99e Initial load
duke
parents:
diff changeset
426 // card can be re-allocated either due to direct allocation
a61af66fc99e Initial load
duke
parents:
diff changeset
427 // or due to absorbing promotions. At this time, the
a61af66fc99e Initial load
duke
parents:
diff changeset
428 // before-gc verification will fail the above assert.
a61af66fc99e Initial load
duke
parents:
diff changeset
429 // (b) MSC: In this case, an object L with a young reference
a61af66fc99e Initial load
duke
parents:
diff changeset
430 // is on a card that (therefore) holds a youngergen_n value.
a61af66fc99e Initial load
duke
parents:
diff changeset
431 // Suppose also that L lies towards the end of the used
a61af66fc99e Initial load
duke
parents:
diff changeset
432 // the used space before GC. An MSC collection
a61af66fc99e Initial load
duke
parents:
diff changeset
433 // occurs that compacts to such an extent that this
a61af66fc99e Initial load
duke
parents:
diff changeset
434 // card is no longer in the occupied part of the space.
a61af66fc99e Initial load
duke
parents:
diff changeset
435 // Since current code in MSC does not always clear cards
a61af66fc99e Initial load
duke
parents:
diff changeset
436 // in the unused part of old gen, this stale youngergen_n
a61af66fc99e Initial load
duke
parents:
diff changeset
437 // value is left behind and can later be covered by
a61af66fc99e Initial load
duke
parents:
diff changeset
438 // an object when promotion or direct allocation
a61af66fc99e Initial load
duke
parents:
diff changeset
439 // re-allocates that part of the heap.
a61af66fc99e Initial load
duke
parents:
diff changeset
440 //
a61af66fc99e Initial load
duke
parents:
diff changeset
441 // Fortunately, the presence of such stale card values is
a61af66fc99e Initial load
duke
parents:
diff changeset
442 // "only" a minor annoyance in that subsequent young collections
a61af66fc99e Initial load
duke
parents:
diff changeset
443 // might needlessly scan such cards, but would still never corrupt
a61af66fc99e Initial load
duke
parents:
diff changeset
444 // the heap as a result. However, it's likely not to be a significant
a61af66fc99e Initial load
duke
parents:
diff changeset
445 // performance inhibitor in practice. For instance,
a61af66fc99e Initial load
duke
parents:
diff changeset
446 // some recent measurements with unoccupied cards eagerly cleared
a61af66fc99e Initial load
duke
parents:
diff changeset
447 // out to maintain this invariant, showed next to no
a61af66fc99e Initial load
duke
parents:
diff changeset
448 // change in young collection times; of course one can construct
a61af66fc99e Initial load
duke
parents:
diff changeset
449 // degenerate examples where the cost can be significant.)
a61af66fc99e Initial load
duke
parents:
diff changeset
450 // Note, in particular, that if the "stale" card is modified
a61af66fc99e Initial load
duke
parents:
diff changeset
451 // after re-allocation, it would be dirty, not "stale". Thus,
a61af66fc99e Initial load
duke
parents:
diff changeset
452 // we can never have a younger ref in such a card and it is
a61af66fc99e Initial load
duke
parents:
diff changeset
453 // safe not to scan that card in any collection. [As we see
a61af66fc99e Initial load
duke
parents:
diff changeset
454 // below, we do some unnecessary scanning
a61af66fc99e Initial load
duke
parents:
diff changeset
455 // in some cases in the current parallel scanning algorithm.]
a61af66fc99e Initial load
duke
parents:
diff changeset
456 //
a61af66fc99e Initial load
duke
parents:
diff changeset
457 // The main point below is that the parallel card scanning code
a61af66fc99e Initial load
duke
parents:
diff changeset
458 // deals correctly with these stale card values. There are two main
a61af66fc99e Initial load
duke
parents:
diff changeset
459 // cases to consider where we have a stale "younger gen" value and a
a61af66fc99e Initial load
duke
parents:
diff changeset
460 // "derivative" case to consider, where we have a stale
a61af66fc99e Initial load
duke
parents:
diff changeset
461 // "cur_younger_gen_and_prev_non_clean" value, as will become
a61af66fc99e Initial load
duke
parents:
diff changeset
462 // apparent in the case analysis below.
a61af66fc99e Initial load
duke
parents:
diff changeset
463 // o Case 1. If the stale value corresponds to a younger_gen_n
a61af66fc99e Initial load
duke
parents:
diff changeset
464 // value other than the cur_younger_gen value then the code
a61af66fc99e Initial load
duke
parents:
diff changeset
465 // treats this as being tantamount to a prev_younger_gen
a61af66fc99e Initial load
duke
parents:
diff changeset
466 // card. This means that the card may be unnecessarily scanned.
a61af66fc99e Initial load
duke
parents:
diff changeset
467 // There are two sub-cases to consider:
a61af66fc99e Initial load
duke
parents:
diff changeset
468 // o Case 1a. Let us say that the card is in the occupied part
a61af66fc99e Initial load
duke
parents:
diff changeset
469 // of the generation at the time the collection begins. In
a61af66fc99e Initial load
duke
parents:
diff changeset
470 // that case the card will be either cleared when it is scanned
a61af66fc99e Initial load
duke
parents:
diff changeset
471 // for young pointers, or will be set to cur_younger_gen as a
a61af66fc99e Initial load
duke
parents:
diff changeset
472 // result of promotion. (We have elided the normal case where
a61af66fc99e Initial load
duke
parents:
diff changeset
473 // the scanning thread and the promoting thread interleave
a61af66fc99e Initial load
duke
parents:
diff changeset
474 // possibly resulting in a transient
a61af66fc99e Initial load
duke
parents:
diff changeset
475 // cur_younger_gen_and_prev_non_clean value before settling
a61af66fc99e Initial load
duke
parents:
diff changeset
476 // to cur_younger_gen. [End Case 1a.]
a61af66fc99e Initial load
duke
parents:
diff changeset
477 // o Case 1b. Consider now the case when the card is in the unoccupied
a61af66fc99e Initial load
duke
parents:
diff changeset
478 // part of the space which becomes occupied because of promotions
a61af66fc99e Initial load
duke
parents:
diff changeset
479 // into it during the current young GC. In this case the card
a61af66fc99e Initial load
duke
parents:
diff changeset
480 // will never be scanned for young references. The current
a61af66fc99e Initial load
duke
parents:
diff changeset
481 // code will set the card value to either
a61af66fc99e Initial load
duke
parents:
diff changeset
482 // cur_younger_gen_and_prev_non_clean or leave
a61af66fc99e Initial load
duke
parents:
diff changeset
483 // it with its stale value -- because the promotions didn't
a61af66fc99e Initial load
duke
parents:
diff changeset
484 // result in any younger refs on that card. Of these two
a61af66fc99e Initial load
duke
parents:
diff changeset
485 // cases, the latter will be covered in Case 1a during
a61af66fc99e Initial load
duke
parents:
diff changeset
486 // a subsequent scan. To deal with the former case, we need
a61af66fc99e Initial load
duke
parents:
diff changeset
487 // to further consider how we deal with a stale value of
a61af66fc99e Initial load
duke
parents:
diff changeset
488 // cur_younger_gen_and_prev_non_clean in our case analysis
a61af66fc99e Initial load
duke
parents:
diff changeset
489 // below. This we do in Case 3 below. [End Case 1b]
a61af66fc99e Initial load
duke
parents:
diff changeset
490 // [End Case 1]
a61af66fc99e Initial load
duke
parents:
diff changeset
491 // o Case 2. If the stale value corresponds to cur_younger_gen being
a61af66fc99e Initial load
duke
parents:
diff changeset
492 // a value not necessarily written by a current promotion, the
a61af66fc99e Initial load
duke
parents:
diff changeset
493 // card will not be scanned by the younger refs scanning code.
a61af66fc99e Initial load
duke
parents:
diff changeset
494 // (This is OK since as we argued above such cards cannot contain
a61af66fc99e Initial load
duke
parents:
diff changeset
495 // any younger refs.) The result is that this value will be
a61af66fc99e Initial load
duke
parents:
diff changeset
496 // treated as a prev_younger_gen value in a subsequent collection,
a61af66fc99e Initial load
duke
parents:
diff changeset
497 // which is addressed in Case 1 above. [End Case 2]
a61af66fc99e Initial load
duke
parents:
diff changeset
498 // o Case 3. We here consider the "derivative" case from Case 1b. above
a61af66fc99e Initial load
duke
parents:
diff changeset
499 // because of which we may find a stale
a61af66fc99e Initial load
duke
parents:
diff changeset
500 // cur_younger_gen_and_prev_non_clean card value in the table.
a61af66fc99e Initial load
duke
parents:
diff changeset
501 // Once again, as in Case 1, we consider two subcases, depending
a61af66fc99e Initial load
duke
parents:
diff changeset
502 // on whether the card lies in the occupied or unoccupied part
a61af66fc99e Initial load
duke
parents:
diff changeset
503 // of the space at the start of the young collection.
a61af66fc99e Initial load
duke
parents:
diff changeset
504 // o Case 3a. Let us say the card is in the occupied part of
a61af66fc99e Initial load
duke
parents:
diff changeset
505 // the old gen at the start of the young collection. In that
a61af66fc99e Initial load
duke
parents:
diff changeset
506 // case, the card will be scanned by the younger refs scanning
a61af66fc99e Initial load
duke
parents:
diff changeset
507 // code which will set it to cur_younger_gen. In a subsequent
a61af66fc99e Initial load
duke
parents:
diff changeset
508 // scan, the card will be considered again and get its final
a61af66fc99e Initial load
duke
parents:
diff changeset
509 // correct value. [End Case 3a]
a61af66fc99e Initial load
duke
parents:
diff changeset
510 // o Case 3b. Now consider the case where the card is in the
a61af66fc99e Initial load
duke
parents:
diff changeset
511 // unoccupied part of the old gen, and is occupied as a result
a61af66fc99e Initial load
duke
parents:
diff changeset
512 // of promotions during thus young gc. In that case,
a61af66fc99e Initial load
duke
parents:
diff changeset
513 // the card will not be scanned for younger refs. The presence
a61af66fc99e Initial load
duke
parents:
diff changeset
514 // of newly promoted objects on the card will then result in
a61af66fc99e Initial load
duke
parents:
diff changeset
515 // its keeping the value cur_younger_gen_and_prev_non_clean
a61af66fc99e Initial load
duke
parents:
diff changeset
516 // value, which we have dealt with in Case 3 here. [End Case 3b]
a61af66fc99e Initial load
duke
parents:
diff changeset
517 // [End Case 3]
a61af66fc99e Initial load
duke
parents:
diff changeset
518 //
a61af66fc99e Initial load
duke
parents:
diff changeset
519 // (Please refer to the code in the helper class
a61af66fc99e Initial load
duke
parents:
diff changeset
520 // ClearNonCleanCardWrapper and in CardTableModRefBS for details.)
a61af66fc99e Initial load
duke
parents:
diff changeset
521 //
a61af66fc99e Initial load
duke
parents:
diff changeset
522 // The informal arguments above can be tightened into a formal
a61af66fc99e Initial load
duke
parents:
diff changeset
523 // correctness proof and it behooves us to write up such a proof,
a61af66fc99e Initial load
duke
parents:
diff changeset
524 // or to use model checking to prove that there are no lingering
a61af66fc99e Initial load
duke
parents:
diff changeset
525 // concerns.
a61af66fc99e Initial load
duke
parents:
diff changeset
526 //
a61af66fc99e Initial load
duke
parents:
diff changeset
527 // Clearly because of Case 3b one cannot bound the time for
a61af66fc99e Initial load
duke
parents:
diff changeset
528 // which a card will retain what we have called a "stale" value.
a61af66fc99e Initial load
duke
parents:
diff changeset
529 // However, one can obtain a Loose upper bound on the redundant
a61af66fc99e Initial load
duke
parents:
diff changeset
530 // work as a result of such stale values. Note first that any
a61af66fc99e Initial load
duke
parents:
diff changeset
531 // time a stale card lies in the occupied part of the space at
a61af66fc99e Initial load
duke
parents:
diff changeset
532 // the start of the collection, it is scanned by younger refs
a61af66fc99e Initial load
duke
parents:
diff changeset
533 // code and we can define a rank function on card values that
a61af66fc99e Initial load
duke
parents:
diff changeset
534 // declines when this is so. Note also that when a card does not
a61af66fc99e Initial load
duke
parents:
diff changeset
535 // lie in the occupied part of the space at the beginning of a
a61af66fc99e Initial load
duke
parents:
diff changeset
536 // young collection, its rank can either decline or stay unchanged.
a61af66fc99e Initial load
duke
parents:
diff changeset
537 // In this case, no extra work is done in terms of redundant
a61af66fc99e Initial load
duke
parents:
diff changeset
538 // younger refs scanning of that card.
a61af66fc99e Initial load
duke
parents:
diff changeset
539 // Then, the case analysis above reveals that, in the worst case,
a61af66fc99e Initial load
duke
parents:
diff changeset
540 // any such stale card will be scanned unnecessarily at most twice.
a61af66fc99e Initial load
duke
parents:
diff changeset
541 //
a61af66fc99e Initial load
duke
parents:
diff changeset
542 // It is nonethelss advisable to try and get rid of some of this
a61af66fc99e Initial load
duke
parents:
diff changeset
543 // redundant work in a subsequent (low priority) re-design of
a61af66fc99e Initial load
duke
parents:
diff changeset
544 // the card-scanning code, if only to simplify the underlying
a61af66fc99e Initial load
duke
parents:
diff changeset
545 // state machine analysis/proof. ysr 1/28/2002. XXX
a61af66fc99e Initial load
duke
parents:
diff changeset
546 cur_entry++;
a61af66fc99e Initial load
duke
parents:
diff changeset
547 }
a61af66fc99e Initial load
duke
parents:
diff changeset
548 }
a61af66fc99e Initial load
duke
parents:
diff changeset
549 }
a61af66fc99e Initial load
duke
parents:
diff changeset
550
a61af66fc99e Initial load
duke
parents:
diff changeset
551 void CardTableRS::verify() {
a61af66fc99e Initial load
duke
parents:
diff changeset
552 // At present, we only know how to verify the card table RS for
a61af66fc99e Initial load
duke
parents:
diff changeset
553 // generational heaps.
a61af66fc99e Initial load
duke
parents:
diff changeset
554 VerifyCTGenClosure blk(this);
a61af66fc99e Initial load
duke
parents:
diff changeset
555 CollectedHeap* ch = Universe::heap();
a61af66fc99e Initial load
duke
parents:
diff changeset
556 // We will do the perm-gen portion of the card table, too.
a61af66fc99e Initial load
duke
parents:
diff changeset
557 Generation* pg = SharedHeap::heap()->perm_gen();
a61af66fc99e Initial load
duke
parents:
diff changeset
558 HeapWord* pg_boundary = pg->reserved().start();
a61af66fc99e Initial load
duke
parents:
diff changeset
559
a61af66fc99e Initial load
duke
parents:
diff changeset
560 if (ch->kind() == CollectedHeap::GenCollectedHeap) {
a61af66fc99e Initial load
duke
parents:
diff changeset
561 GenCollectedHeap::heap()->generation_iterate(&blk, false);
342
37f87013dfd8 6711316: Open source the Garbage-First garbage collector
ysr
parents: 113
diff changeset
562 _ct_bs->verify();
0
a61af66fc99e Initial load
duke
parents:
diff changeset
563
a61af66fc99e Initial load
duke
parents:
diff changeset
564 // If the old gen collections also collect perm, then we are only
a61af66fc99e Initial load
duke
parents:
diff changeset
565 // interested in perm-to-young pointers, not perm-to-old pointers.
a61af66fc99e Initial load
duke
parents:
diff changeset
566 GenCollectedHeap* gch = GenCollectedHeap::heap();
a61af66fc99e Initial load
duke
parents:
diff changeset
567 CollectorPolicy* cp = gch->collector_policy();
a61af66fc99e Initial load
duke
parents:
diff changeset
568 if (cp->is_mark_sweep_policy() || cp->is_concurrent_mark_sweep_policy()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
569 pg_boundary = gch->get_gen(1)->reserved().start();
a61af66fc99e Initial load
duke
parents:
diff changeset
570 }
a61af66fc99e Initial load
duke
parents:
diff changeset
571 }
a61af66fc99e Initial load
duke
parents:
diff changeset
572 VerifyCTSpaceClosure perm_space_blk(this, pg_boundary);
a61af66fc99e Initial load
duke
parents:
diff changeset
573 SharedHeap::heap()->perm_gen()->space_iterate(&perm_space_blk, true);
a61af66fc99e Initial load
duke
parents:
diff changeset
574 }
a61af66fc99e Initial load
duke
parents:
diff changeset
575
a61af66fc99e Initial load
duke
parents:
diff changeset
576
6
73e96e5c30df 6624765: Guarantee failure "Unexpected dirty card found"
jmasa
parents: 0
diff changeset
577 void CardTableRS::verify_aligned_region_empty(MemRegion mr) {
0
a61af66fc99e Initial load
duke
parents:
diff changeset
578 if (!mr.is_empty()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
579 jbyte* cur_entry = byte_for(mr.start());
a61af66fc99e Initial load
duke
parents:
diff changeset
580 jbyte* limit = byte_after(mr.last());
6
73e96e5c30df 6624765: Guarantee failure "Unexpected dirty card found"
jmasa
parents: 0
diff changeset
581 // The region mr may not start on a card boundary so
73e96e5c30df 6624765: Guarantee failure "Unexpected dirty card found"
jmasa
parents: 0
diff changeset
582 // the first card may reflect a write to the space
73e96e5c30df 6624765: Guarantee failure "Unexpected dirty card found"
jmasa
parents: 0
diff changeset
583 // just prior to mr.
73e96e5c30df 6624765: Guarantee failure "Unexpected dirty card found"
jmasa
parents: 0
diff changeset
584 if (!is_aligned(mr.start())) {
73e96e5c30df 6624765: Guarantee failure "Unexpected dirty card found"
jmasa
parents: 0
diff changeset
585 cur_entry++;
73e96e5c30df 6624765: Guarantee failure "Unexpected dirty card found"
jmasa
parents: 0
diff changeset
586 }
0
a61af66fc99e Initial load
duke
parents:
diff changeset
587 for (;cur_entry < limit; cur_entry++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
588 guarantee(*cur_entry == CardTableModRefBS::clean_card,
a61af66fc99e Initial load
duke
parents:
diff changeset
589 "Unexpected dirty card found");
a61af66fc99e Initial load
duke
parents:
diff changeset
590 }
a61af66fc99e Initial load
duke
parents:
diff changeset
591 }
a61af66fc99e Initial load
duke
parents:
diff changeset
592 }