annotate src/share/vm/memory/cardTableRS.cpp @ 1994:6cd6d394f280

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