Mercurial > hg > truffle
annotate src/share/vm/memory/cardTableRS.cpp @ 20543:e7d0505c8a30
8059758: Footprint regressions with JDK-8038423
Summary: Changes in JDK-8038423 always initialize (zero out) virtual memory used for auxiliary data structures. This causes a footprint regression for G1 in startup benchmarks. This is because they do not touch that memory at all, so the operating system does not actually commit these pages. The fix is to, if the initialization value of the data structures matches the default value of just committed memory (=0), do not do anything.
Reviewed-by: jwilhelm, brutisso
author | tschatzl |
---|---|
date | Fri, 10 Oct 2014 15:51:58 +0200 |
parents | 833b0f92429a |
children | 7848fc12602b |
rev | line source |
---|---|
0 | 1 /* |
17937
78bbf4d43a14
8037816: Fix for 8036122 breaks build with Xcode5/clang
drchase
parents:
12033
diff
changeset
|
2 * Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved. |
0 | 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * | |
5 * This code is free software; you can redistribute it and/or modify it | |
6 * under the terms of the GNU General Public License version 2 only, as | |
7 * published by the Free Software Foundation. | |
8 * | |
9 * This code is distributed in the hope that it will be useful, but WITHOUT | |
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
12 * version 2 for more details (a copy is included in the LICENSE file that | |
13 * accompanied this code). | |
14 * | |
15 * You should have received a copy of the GNU General Public License version | |
16 * 2 along with this work; if not, write to the Free Software Foundation, | |
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
18 * | |
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 | 22 * |
23 */ | |
24 | |
1972 | 25 #include "precompiled.hpp" |
26 #include "memory/allocation.inline.hpp" | |
27 #include "memory/cardTableRS.hpp" | |
28 #include "memory/genCollectedHeap.hpp" | |
29 #include "memory/generation.hpp" | |
30 #include "memory/space.hpp" | |
31 #include "oops/oop.inline.hpp" | |
32 #include "runtime/java.hpp" | |
33 #include "runtime/os.hpp" | |
8001
db9981fd3124
8005915: Unify SERIALGC and INCLUDE_ALTERNATE_GCS
jprovino
parents:
6725
diff
changeset
|
34 #include "utilities/macros.hpp" |
db9981fd3124
8005915: Unify SERIALGC and INCLUDE_ALTERNATE_GCS
jprovino
parents:
6725
diff
changeset
|
35 #if INCLUDE_ALL_GCS |
1972 | 36 #include "gc_implementation/g1/concurrentMark.hpp" |
37 #include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp" | |
8001
db9981fd3124
8005915: Unify SERIALGC and INCLUDE_ALTERNATE_GCS
jprovino
parents:
6725
diff
changeset
|
38 #endif // INCLUDE_ALL_GCS |
0 | 39 |
40 CardTableRS::CardTableRS(MemRegion whole_heap, | |
41 int max_covered_regions) : | |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
42 GenRemSet(), |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
43 _cur_youngergen_card_val(youngergenP1_card), |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
44 _regions_to_iterate(max_covered_regions - 1) |
0 | 45 { |
8001
db9981fd3124
8005915: Unify SERIALGC and INCLUDE_ALTERNATE_GCS
jprovino
parents:
6725
diff
changeset
|
46 #if INCLUDE_ALL_GCS |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
47 if (UseG1GC) { |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
48 _ct_bs = new G1SATBCardTableLoggingModRefBS(whole_heap, |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
49 max_covered_regions); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
50 } else { |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
51 _ct_bs = new CardTableModRefBSForCTRS(whole_heap, max_covered_regions); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
52 } |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
53 #else |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
54 _ct_bs = new CardTableModRefBSForCTRS(whole_heap, max_covered_regions); |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
55 #endif |
20337 | 56 _ct_bs->initialize(); |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
57 set_bs(_ct_bs); |
10271
f9be75d21404
8012902: remove use of global operator new - take 2
minqi
parents:
10135
diff
changeset
|
58 _last_cur_val_in_gen = NEW_C_HEAP_ARRAY3(jbyte, GenCollectedHeap::max_gens + 1, |
20360 | 59 mtGC, CURRENT_PC, AllocFailStrategy::RETURN_NULL); |
0 | 60 if (_last_cur_val_in_gen == NULL) { |
10271
f9be75d21404
8012902: remove use of global operator new - take 2
minqi
parents:
10135
diff
changeset
|
61 vm_exit_during_initialization("Could not create last_cur_val_in_gen array."); |
0 | 62 } |
63 for (int i = 0; i < GenCollectedHeap::max_gens + 1; i++) { | |
64 _last_cur_val_in_gen[i] = clean_card_val(); | |
65 } | |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
66 _ct_bs->set_CTRS(this); |
0 | 67 } |
68 | |
10271
f9be75d21404
8012902: remove use of global operator new - take 2
minqi
parents:
10135
diff
changeset
|
69 CardTableRS::~CardTableRS() { |
f9be75d21404
8012902: remove use of global operator new - take 2
minqi
parents:
10135
diff
changeset
|
70 if (_ct_bs) { |
f9be75d21404
8012902: remove use of global operator new - take 2
minqi
parents:
10135
diff
changeset
|
71 delete _ct_bs; |
f9be75d21404
8012902: remove use of global operator new - take 2
minqi
parents:
10135
diff
changeset
|
72 _ct_bs = NULL; |
f9be75d21404
8012902: remove use of global operator new - take 2
minqi
parents:
10135
diff
changeset
|
73 } |
f9be75d21404
8012902: remove use of global operator new - take 2
minqi
parents:
10135
diff
changeset
|
74 if (_last_cur_val_in_gen) { |
f9be75d21404
8012902: remove use of global operator new - take 2
minqi
parents:
10135
diff
changeset
|
75 FREE_C_HEAP_ARRAY(jbyte, _last_cur_val_in_gen, mtInternal); |
f9be75d21404
8012902: remove use of global operator new - take 2
minqi
parents:
10135
diff
changeset
|
76 } |
f9be75d21404
8012902: remove use of global operator new - take 2
minqi
parents:
10135
diff
changeset
|
77 } |
f9be75d21404
8012902: remove use of global operator new - take 2
minqi
parents:
10135
diff
changeset
|
78 |
0 | 79 void CardTableRS::resize_covered_region(MemRegion new_region) { |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
80 _ct_bs->resize_covered_region(new_region); |
0 | 81 } |
82 | |
83 jbyte CardTableRS::find_unused_youngergenP_card_value() { | |
84 for (jbyte v = youngergenP1_card; | |
85 v < cur_youngergen_and_prev_nonclean_card; | |
86 v++) { | |
87 bool seen = false; | |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
88 for (int g = 0; g < _regions_to_iterate; g++) { |
0 | 89 if (_last_cur_val_in_gen[g] == v) { |
90 seen = true; | |
91 break; | |
92 } | |
93 } | |
94 if (!seen) return v; | |
95 } | |
96 ShouldNotReachHere(); | |
97 return 0; | |
98 } | |
99 | |
100 void CardTableRS::prepare_for_younger_refs_iterate(bool parallel) { | |
101 // Parallel or sequential, we must always set the prev to equal the | |
102 // last one written. | |
103 if (parallel) { | |
104 // Find a parallel value to be used next. | |
105 jbyte next_val = find_unused_youngergenP_card_value(); | |
106 set_cur_youngergen_card_val(next_val); | |
107 | |
108 } else { | |
109 // In an sequential traversal we will always write youngergen, so that | |
110 // the inline barrier is correct. | |
111 set_cur_youngergen_card_val(youngergen_card); | |
112 } | |
113 } | |
114 | |
115 void CardTableRS::younger_refs_iterate(Generation* g, | |
116 OopsInGenClosure* blk) { | |
117 _last_cur_val_in_gen[g->level()+1] = cur_youngergen_card_val(); | |
118 g->younger_refs_iterate(blk); | |
119 } | |
120 | |
3287
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
121 inline bool ClearNoncleanCardWrapper::clear_card(jbyte* entry) { |
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
122 if (_is_par) { |
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
123 return clear_card_parallel(entry); |
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
124 } else { |
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
125 return clear_card_serial(entry); |
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
126 } |
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
127 } |
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
128 |
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
129 inline bool ClearNoncleanCardWrapper::clear_card_parallel(jbyte* entry) { |
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
130 while (true) { |
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
131 // In the parallel case, we may have to do this several times. |
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
132 jbyte entry_val = *entry; |
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
133 assert(entry_val != CardTableRS::clean_card_val(), |
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
134 "We shouldn't be looking at clean cards, and this should " |
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
135 "be the only place they get cleaned."); |
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
136 if (CardTableRS::card_is_dirty_wrt_gen_iter(entry_val) |
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
137 || _ct->is_prev_youngergen_card_val(entry_val)) { |
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
138 jbyte res = |
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
139 Atomic::cmpxchg(CardTableRS::clean_card_val(), entry, entry_val); |
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
140 if (res == entry_val) { |
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
141 break; |
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
142 } else { |
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
143 assert(res == CardTableRS::cur_youngergen_and_prev_nonclean_card, |
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
144 "The CAS above should only fail if another thread did " |
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
145 "a GC write barrier."); |
0 | 146 } |
3287
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
147 } else if (entry_val == |
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
148 CardTableRS::cur_youngergen_and_prev_nonclean_card) { |
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
149 // Parallelism shouldn't matter in this case. Only the thread |
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
150 // assigned to scan the card should change this value. |
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
151 *entry = _ct->cur_youngergen_card_val(); |
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
152 break; |
0 | 153 } else { |
3287
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
154 assert(entry_val == _ct->cur_youngergen_card_val(), |
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
155 "Should be the only possibility."); |
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
156 // In this case, the card was clean before, and become |
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
157 // cur_youngergen only because of processing of a promoted object. |
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
158 // We don't have to look at the card. |
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
159 return false; |
0 | 160 } |
161 } | |
3287
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
162 return true; |
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
163 } |
0 | 164 |
3287
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
165 |
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
166 inline bool ClearNoncleanCardWrapper::clear_card_serial(jbyte* entry) { |
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
167 jbyte entry_val = *entry; |
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
168 assert(entry_val != CardTableRS::clean_card_val(), |
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
169 "We shouldn't be looking at clean cards, and this should " |
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
170 "be the only place they get cleaned."); |
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
171 assert(entry_val != CardTableRS::cur_youngergen_and_prev_nonclean_card, |
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
172 "This should be possible in the sequential case."); |
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
173 *entry = CardTableRS::clean_card_val(); |
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
174 return true; |
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
175 } |
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
176 |
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
177 ClearNoncleanCardWrapper::ClearNoncleanCardWrapper( |
3357
fc2b798ab316
6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents:
3293
diff
changeset
|
178 DirtyCardToOopClosure* dirty_card_closure, CardTableRS* ct) : |
0 | 179 _dirty_card_closure(dirty_card_closure), _ct(ct) { |
4095
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
3357
diff
changeset
|
180 // Cannot yet substitute active_workers for n_par_threads |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
3357
diff
changeset
|
181 // in the case where parallelism is being turned off by |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
3357
diff
changeset
|
182 // setting n_par_threads to 0. |
0 | 183 _is_par = (SharedHeap::heap()->n_par_threads() > 0); |
4095
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
3357
diff
changeset
|
184 assert(!_is_par || |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
3357
diff
changeset
|
185 (SharedHeap::heap()->n_par_threads() == |
bca17e38de00
6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads
jmasa
parents:
3357
diff
changeset
|
186 SharedHeap::heap()->workers()->active_workers()), "Mismatch"); |
3287
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
187 } |
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
188 |
5939
c7a555a9449a
7068625: Testing 8 bytes of card table entries at a time speeds up card-scanning
brutisso
parents:
4095
diff
changeset
|
189 bool ClearNoncleanCardWrapper::is_word_aligned(jbyte* entry) { |
c7a555a9449a
7068625: Testing 8 bytes of card table entries at a time speeds up card-scanning
brutisso
parents:
4095
diff
changeset
|
190 return (((intptr_t)entry) & (BytesPerWord-1)) == 0; |
c7a555a9449a
7068625: Testing 8 bytes of card table entries at a time speeds up card-scanning
brutisso
parents:
4095
diff
changeset
|
191 } |
c7a555a9449a
7068625: Testing 8 bytes of card table entries at a time speeds up card-scanning
brutisso
parents:
4095
diff
changeset
|
192 |
3287
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
193 void ClearNoncleanCardWrapper::do_MemRegion(MemRegion mr) { |
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
194 assert(mr.word_size() > 0, "Error"); |
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
195 assert(_ct->is_aligned(mr.start()), "mr.start() should be card aligned"); |
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
196 // mr.end() may not necessarily be card aligned. |
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
197 jbyte* cur_entry = _ct->byte_for(mr.last()); |
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
198 const jbyte* limit = _ct->byte_for(mr.start()); |
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
199 HeapWord* end_of_non_clean = mr.end(); |
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
200 HeapWord* start_of_non_clean = end_of_non_clean; |
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
201 while (cur_entry >= limit) { |
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
202 HeapWord* cur_hw = _ct->addr_for(cur_entry); |
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
203 if ((*cur_entry != CardTableRS::clean_card_val()) && clear_card(cur_entry)) { |
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
204 // Continue the dirty range by opening the |
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
205 // dirty window one card to the left. |
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
206 start_of_non_clean = cur_hw; |
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
207 } else { |
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
208 // We hit a "clean" card; process any non-empty |
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
209 // "dirty" range accumulated so far. |
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
210 if (start_of_non_clean < end_of_non_clean) { |
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
211 const MemRegion mrd(start_of_non_clean, end_of_non_clean); |
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
212 _dirty_card_closure->do_MemRegion(mrd); |
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
213 } |
5939
c7a555a9449a
7068625: Testing 8 bytes of card table entries at a time speeds up card-scanning
brutisso
parents:
4095
diff
changeset
|
214 |
c7a555a9449a
7068625: Testing 8 bytes of card table entries at a time speeds up card-scanning
brutisso
parents:
4095
diff
changeset
|
215 // fast forward through potential continuous whole-word range of clean cards beginning at a word-boundary |
c7a555a9449a
7068625: Testing 8 bytes of card table entries at a time speeds up card-scanning
brutisso
parents:
4095
diff
changeset
|
216 if (is_word_aligned(cur_entry)) { |
c7a555a9449a
7068625: Testing 8 bytes of card table entries at a time speeds up card-scanning
brutisso
parents:
4095
diff
changeset
|
217 jbyte* cur_row = cur_entry - BytesPerWord; |
c7a555a9449a
7068625: Testing 8 bytes of card table entries at a time speeds up card-scanning
brutisso
parents:
4095
diff
changeset
|
218 while (cur_row >= limit && *((intptr_t*)cur_row) == CardTableRS::clean_card_row()) { |
c7a555a9449a
7068625: Testing 8 bytes of card table entries at a time speeds up card-scanning
brutisso
parents:
4095
diff
changeset
|
219 cur_row -= BytesPerWord; |
c7a555a9449a
7068625: Testing 8 bytes of card table entries at a time speeds up card-scanning
brutisso
parents:
4095
diff
changeset
|
220 } |
c7a555a9449a
7068625: Testing 8 bytes of card table entries at a time speeds up card-scanning
brutisso
parents:
4095
diff
changeset
|
221 cur_entry = cur_row + BytesPerWord; |
c7a555a9449a
7068625: Testing 8 bytes of card table entries at a time speeds up card-scanning
brutisso
parents:
4095
diff
changeset
|
222 cur_hw = _ct->addr_for(cur_entry); |
c7a555a9449a
7068625: Testing 8 bytes of card table entries at a time speeds up card-scanning
brutisso
parents:
4095
diff
changeset
|
223 } |
c7a555a9449a
7068625: Testing 8 bytes of card table entries at a time speeds up card-scanning
brutisso
parents:
4095
diff
changeset
|
224 |
3287
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
225 // Reset the dirty window, while continuing to look |
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
226 // for the next dirty card that will start a |
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
227 // new dirty window. |
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
228 end_of_non_clean = cur_hw; |
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
229 start_of_non_clean = cur_hw; |
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
230 } |
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
231 // Note that "cur_entry" leads "start_of_non_clean" in |
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
232 // its leftward excursion after this point |
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
233 // in the loop and, when we hit the left end of "mr", |
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
234 // will point off of the left end of the card-table |
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
235 // for "mr". |
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
236 cur_entry--; |
0 | 237 } |
3287
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
238 // If the first card of "mr" was dirty, we will have |
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
239 // been left with a dirty window, co-initial with "mr", |
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
240 // which we now process. |
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
241 if (start_of_non_clean < end_of_non_clean) { |
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
242 const MemRegion mrd(start_of_non_clean, end_of_non_clean); |
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
243 _dirty_card_closure->do_MemRegion(mrd); |
0 | 244 } |
3287
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
245 } |
c48ad6ab8bdf
7037276: Unnecessary double traversal of dirty card windows
ysr
parents:
3256
diff
changeset
|
246 |
0 | 247 // clean (by dirty->clean before) ==> cur_younger_gen |
248 // dirty ==> cur_youngergen_and_prev_nonclean_card | |
249 // precleaned ==> cur_youngergen_and_prev_nonclean_card | |
250 // prev-younger-gen ==> cur_youngergen_and_prev_nonclean_card | |
251 // cur-younger-gen ==> cur_younger_gen | |
252 // 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
|
253 void CardTableRS::write_ref_field_gc_par(void* field, oop new_val) { |
0 | 254 jbyte* entry = ct_bs()->byte_for(field); |
255 do { | |
256 jbyte entry_val = *entry; | |
257 // We put this first because it's probably the most common case. | |
258 if (entry_val == clean_card_val()) { | |
259 // No threat of contention with cleaning threads. | |
260 *entry = cur_youngergen_card_val(); | |
261 return; | |
262 } else if (card_is_dirty_wrt_gen_iter(entry_val) | |
263 || is_prev_youngergen_card_val(entry_val)) { | |
264 // Mark it as both cur and prev youngergen; card cleaning thread will | |
265 // eventually remove the previous stuff. | |
266 jbyte new_val = cur_youngergen_and_prev_nonclean_card; | |
267 jbyte res = Atomic::cmpxchg(new_val, entry, entry_val); | |
268 // Did the CAS succeed? | |
269 if (res == entry_val) return; | |
270 // Otherwise, retry, to see the new value. | |
271 continue; | |
272 } else { | |
273 assert(entry_val == cur_youngergen_and_prev_nonclean_card | |
274 || entry_val == cur_youngergen_card_val(), | |
275 "should be only possibilities."); | |
276 return; | |
277 } | |
278 } while (true); | |
279 } | |
280 | |
281 void CardTableRS::younger_refs_in_space_iterate(Space* sp, | |
282 OopsInGenClosure* cl) { | |
3293
1f4413413144
7039089: G1: changeset for 7037276 broke heap verification, and related cleanups
ysr
parents:
3287
diff
changeset
|
283 const MemRegion urasm = sp->used_region_at_save_marks(); |
1f4413413144
7039089: G1: changeset for 7037276 broke heap verification, and related cleanups
ysr
parents:
3287
diff
changeset
|
284 #ifdef ASSERT |
1f4413413144
7039089: G1: changeset for 7037276 broke heap verification, and related cleanups
ysr
parents:
3287
diff
changeset
|
285 // Convert the assertion check to a warning if we are running |
1f4413413144
7039089: G1: changeset for 7037276 broke heap verification, and related cleanups
ysr
parents:
3287
diff
changeset
|
286 // CMS+ParNew until related bug is fixed. |
1f4413413144
7039089: G1: changeset for 7037276 broke heap verification, and related cleanups
ysr
parents:
3287
diff
changeset
|
287 MemRegion ur = sp->used_region(); |
1f4413413144
7039089: G1: changeset for 7037276 broke heap verification, and related cleanups
ysr
parents:
3287
diff
changeset
|
288 assert(ur.contains(urasm) || (UseConcMarkSweepGC && UseParNewGC), |
1f4413413144
7039089: G1: changeset for 7037276 broke heap verification, and related cleanups
ysr
parents:
3287
diff
changeset
|
289 err_msg("Did you forget to call save_marks()? " |
1f4413413144
7039089: G1: changeset for 7037276 broke heap verification, and related cleanups
ysr
parents:
3287
diff
changeset
|
290 "[" PTR_FORMAT ", " PTR_FORMAT ") is not contained in " |
1f4413413144
7039089: G1: changeset for 7037276 broke heap verification, and related cleanups
ysr
parents:
3287
diff
changeset
|
291 "[" PTR_FORMAT ", " PTR_FORMAT ")", |
17937
78bbf4d43a14
8037816: Fix for 8036122 breaks build with Xcode5/clang
drchase
parents:
12033
diff
changeset
|
292 p2i(urasm.start()), p2i(urasm.end()), p2i(ur.start()), p2i(ur.end()))); |
3293
1f4413413144
7039089: G1: changeset for 7037276 broke heap verification, and related cleanups
ysr
parents:
3287
diff
changeset
|
293 // In the case of CMS+ParNew, issue a warning |
1f4413413144
7039089: G1: changeset for 7037276 broke heap verification, and related cleanups
ysr
parents:
3287
diff
changeset
|
294 if (!ur.contains(urasm)) { |
1f4413413144
7039089: G1: changeset for 7037276 broke heap verification, and related cleanups
ysr
parents:
3287
diff
changeset
|
295 assert(UseConcMarkSweepGC && UseParNewGC, "Tautology: see assert above"); |
1f4413413144
7039089: G1: changeset for 7037276 broke heap verification, and related cleanups
ysr
parents:
3287
diff
changeset
|
296 warning("CMS+ParNew: Did you forget to call save_marks()? " |
1f4413413144
7039089: G1: changeset for 7037276 broke heap verification, and related cleanups
ysr
parents:
3287
diff
changeset
|
297 "[" PTR_FORMAT ", " PTR_FORMAT ") is not contained in " |
1f4413413144
7039089: G1: changeset for 7037276 broke heap verification, and related cleanups
ysr
parents:
3287
diff
changeset
|
298 "[" PTR_FORMAT ", " PTR_FORMAT ")", |
17937
78bbf4d43a14
8037816: Fix for 8036122 breaks build with Xcode5/clang
drchase
parents:
12033
diff
changeset
|
299 p2i(urasm.start()), p2i(urasm.end()), p2i(ur.start()), p2i(ur.end())); |
3293
1f4413413144
7039089: G1: changeset for 7037276 broke heap verification, and related cleanups
ysr
parents:
3287
diff
changeset
|
300 MemRegion ur2 = sp->used_region(); |
1f4413413144
7039089: G1: changeset for 7037276 broke heap verification, and related cleanups
ysr
parents:
3287
diff
changeset
|
301 MemRegion urasm2 = sp->used_region_at_save_marks(); |
1f4413413144
7039089: G1: changeset for 7037276 broke heap verification, and related cleanups
ysr
parents:
3287
diff
changeset
|
302 if (!ur.equals(ur2)) { |
1f4413413144
7039089: G1: changeset for 7037276 broke heap verification, and related cleanups
ysr
parents:
3287
diff
changeset
|
303 warning("CMS+ParNew: Flickering used_region()!!"); |
1f4413413144
7039089: G1: changeset for 7037276 broke heap verification, and related cleanups
ysr
parents:
3287
diff
changeset
|
304 } |
1f4413413144
7039089: G1: changeset for 7037276 broke heap verification, and related cleanups
ysr
parents:
3287
diff
changeset
|
305 if (!urasm.equals(urasm2)) { |
1f4413413144
7039089: G1: changeset for 7037276 broke heap verification, and related cleanups
ysr
parents:
3287
diff
changeset
|
306 warning("CMS+ParNew: Flickering used_region_at_save_marks()!!"); |
1f4413413144
7039089: G1: changeset for 7037276 broke heap verification, and related cleanups
ysr
parents:
3287
diff
changeset
|
307 } |
3357
fc2b798ab316
6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents:
3293
diff
changeset
|
308 ShouldNotReachHere(); |
3293
1f4413413144
7039089: G1: changeset for 7037276 broke heap verification, and related cleanups
ysr
parents:
3287
diff
changeset
|
309 } |
1f4413413144
7039089: G1: changeset for 7037276 broke heap verification, and related cleanups
ysr
parents:
3287
diff
changeset
|
310 #endif |
3357
fc2b798ab316
6883834: ParNew: assert(!_g->to()->is_in_reserved(obj),"Scanning field twice?") with LargeObjects tests
ysr
parents:
3293
diff
changeset
|
311 _ct_bs->non_clean_card_iterate_possibly_parallel(sp, urasm, cl, this); |
0 | 312 } |
313 | |
12033
bd902affe102
8023021: Unnecessary clearing of the card table introduced by the fix for JDK-8023013
brutisso
parents:
12030
diff
changeset
|
314 void CardTableRS::clear_into_younger(Generation* old_gen) { |
bd902affe102
8023021: Unnecessary clearing of the card table introduced by the fix for JDK-8023013
brutisso
parents:
12030
diff
changeset
|
315 assert(old_gen->level() == 1, "Should only be called for the old generation"); |
bd902affe102
8023021: Unnecessary clearing of the card table introduced by the fix for JDK-8023013
brutisso
parents:
12030
diff
changeset
|
316 // The card tables for the youngest gen need never be cleared. |
0 | 317 // There's a bit of subtlety in the clear() and invalidate() |
318 // methods that we exploit here and in invalidate_or_clear() | |
319 // below to avoid missing cards at the fringes. If clear() or | |
320 // invalidate() are changed in the future, this code should | |
321 // be revisited. 20040107.ysr | |
12030
330dfb0476f4
8022800: Use specific generations rather than generation iteration
brutisso
parents:
10271
diff
changeset
|
322 clear(old_gen->prev_used_region()); |
0 | 323 } |
324 | |
12033
bd902affe102
8023021: Unnecessary clearing of the card table introduced by the fix for JDK-8023013
brutisso
parents:
12030
diff
changeset
|
325 void CardTableRS::invalidate_or_clear(Generation* old_gen) { |
bd902affe102
8023021: Unnecessary clearing of the card table introduced by the fix for JDK-8023013
brutisso
parents:
12030
diff
changeset
|
326 assert(old_gen->level() == 1, "Should only be called for the old generation"); |
bd902affe102
8023021: Unnecessary clearing of the card table introduced by the fix for JDK-8023013
brutisso
parents:
12030
diff
changeset
|
327 // Invalidate the cards for the currently occupied part of |
bd902affe102
8023021: Unnecessary clearing of the card table introduced by the fix for JDK-8023013
brutisso
parents:
12030
diff
changeset
|
328 // the old generation and clear the cards for the |
0 | 329 // unoccupied part of the generation (if any, making use |
330 // of that generation's prev_used_region to determine that | |
331 // region). No need to do anything for the youngest | |
332 // generation. Also see note#20040107.ysr above. | |
12033
bd902affe102
8023021: Unnecessary clearing of the card table introduced by the fix for JDK-8023013
brutisso
parents:
12030
diff
changeset
|
333 MemRegion used_mr = old_gen->used_region(); |
bd902affe102
8023021: Unnecessary clearing of the card table introduced by the fix for JDK-8023013
brutisso
parents:
12030
diff
changeset
|
334 MemRegion to_be_cleared_mr = old_gen->prev_used_region().minus(used_mr); |
12030
330dfb0476f4
8022800: Use specific generations rather than generation iteration
brutisso
parents:
10271
diff
changeset
|
335 if (!to_be_cleared_mr.is_empty()) { |
330dfb0476f4
8022800: Use specific generations rather than generation iteration
brutisso
parents:
10271
diff
changeset
|
336 clear(to_be_cleared_mr); |
0 | 337 } |
12030
330dfb0476f4
8022800: Use specific generations rather than generation iteration
brutisso
parents:
10271
diff
changeset
|
338 invalidate(used_mr); |
0 | 339 } |
340 | |
341 | |
342 class VerifyCleanCardClosure: public OopClosure { | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
6
diff
changeset
|
343 private: |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
6
diff
changeset
|
344 HeapWord* _boundary; |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
6
diff
changeset
|
345 HeapWord* _begin; |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
6
diff
changeset
|
346 HeapWord* _end; |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
6
diff
changeset
|
347 protected: |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
6
diff
changeset
|
348 template <class T> void do_oop_work(T* p) { |
0 | 349 HeapWord* jp = (HeapWord*)p; |
2428
5134fa1cfe63
7029036: Card-table verification hangs with all framework collectors, except G1, even before the first GC
ysr
parents:
1972
diff
changeset
|
350 assert(jp >= _begin && jp < _end, |
5134fa1cfe63
7029036: Card-table verification hangs with all framework collectors, except G1, even before the first GC
ysr
parents:
1972
diff
changeset
|
351 err_msg("Error: jp " PTR_FORMAT " should be within " |
5134fa1cfe63
7029036: Card-table verification hangs with all framework collectors, except G1, even before the first GC
ysr
parents:
1972
diff
changeset
|
352 "[_begin, _end) = [" PTR_FORMAT "," PTR_FORMAT ")", |
17937
78bbf4d43a14
8037816: Fix for 8036122 breaks build with Xcode5/clang
drchase
parents:
12033
diff
changeset
|
353 p2i(jp), p2i(_begin), p2i(_end))); |
2428
5134fa1cfe63
7029036: Card-table verification hangs with all framework collectors, except G1, even before the first GC
ysr
parents:
1972
diff
changeset
|
354 oop obj = oopDesc::load_decode_heap_oop(p); |
5134fa1cfe63
7029036: Card-table verification hangs with all framework collectors, except G1, even before the first GC
ysr
parents:
1972
diff
changeset
|
355 guarantee(obj == NULL || (HeapWord*)obj >= _boundary, |
5134fa1cfe63
7029036: Card-table verification hangs with all framework collectors, except G1, even before the first GC
ysr
parents:
1972
diff
changeset
|
356 err_msg("pointer " PTR_FORMAT " at " PTR_FORMAT " on " |
5134fa1cfe63
7029036: Card-table verification hangs with all framework collectors, except G1, even before the first GC
ysr
parents:
1972
diff
changeset
|
357 "clean card crosses boundary" PTR_FORMAT, |
17937
78bbf4d43a14
8037816: Fix for 8036122 breaks build with Xcode5/clang
drchase
parents:
12033
diff
changeset
|
358 p2i((HeapWord*)obj), p2i(jp), p2i(_boundary))); |
0 | 359 } |
2428
5134fa1cfe63
7029036: Card-table verification hangs with all framework collectors, except G1, even before the first GC
ysr
parents:
1972
diff
changeset
|
360 |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
6
diff
changeset
|
361 public: |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
6
diff
changeset
|
362 VerifyCleanCardClosure(HeapWord* b, HeapWord* begin, HeapWord* end) : |
2428
5134fa1cfe63
7029036: Card-table verification hangs with all framework collectors, except G1, even before the first GC
ysr
parents:
1972
diff
changeset
|
363 _boundary(b), _begin(begin), _end(end) { |
5134fa1cfe63
7029036: Card-table verification hangs with all framework collectors, except G1, even before the first GC
ysr
parents:
1972
diff
changeset
|
364 assert(b <= begin, |
5134fa1cfe63
7029036: Card-table verification hangs with all framework collectors, except G1, even before the first GC
ysr
parents:
1972
diff
changeset
|
365 err_msg("Error: boundary " PTR_FORMAT " should be at or below begin " PTR_FORMAT, |
17937
78bbf4d43a14
8037816: Fix for 8036122 breaks build with Xcode5/clang
drchase
parents:
12033
diff
changeset
|
366 p2i(b), p2i(begin))); |
2428
5134fa1cfe63
7029036: Card-table verification hangs with all framework collectors, except G1, even before the first GC
ysr
parents:
1972
diff
changeset
|
367 assert(begin <= end, |
5134fa1cfe63
7029036: Card-table verification hangs with all framework collectors, except G1, even before the first GC
ysr
parents:
1972
diff
changeset
|
368 err_msg("Error: begin " PTR_FORMAT " should be strictly below end " PTR_FORMAT, |
17937
78bbf4d43a14
8037816: Fix for 8036122 breaks build with Xcode5/clang
drchase
parents:
12033
diff
changeset
|
369 p2i(begin), p2i(end))); |
2428
5134fa1cfe63
7029036: Card-table verification hangs with all framework collectors, except G1, even before the first GC
ysr
parents:
1972
diff
changeset
|
370 } |
5134fa1cfe63
7029036: Card-table verification hangs with all framework collectors, except G1, even before the first GC
ysr
parents:
1972
diff
changeset
|
371 |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
6
diff
changeset
|
372 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
|
373 virtual void do_oop(narrowOop* p) { VerifyCleanCardClosure::do_oop_work(p); } |
0 | 374 }; |
375 | |
376 class VerifyCTSpaceClosure: public SpaceClosure { | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
6
diff
changeset
|
377 private: |
0 | 378 CardTableRS* _ct; |
379 HeapWord* _boundary; | |
380 public: | |
381 VerifyCTSpaceClosure(CardTableRS* ct, HeapWord* boundary) : | |
382 _ct(ct), _boundary(boundary) {} | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
6
diff
changeset
|
383 virtual void do_space(Space* s) { _ct->verify_space(s, _boundary); } |
0 | 384 }; |
385 | |
386 class VerifyCTGenClosure: public GenCollectedHeap::GenClosure { | |
387 CardTableRS* _ct; | |
388 public: | |
389 VerifyCTGenClosure(CardTableRS* ct) : _ct(ct) {} | |
390 void do_generation(Generation* gen) { | |
391 // Skip the youngest generation. | |
392 if (gen->level() == 0) return; | |
393 // Normally, we're interested in pointers to younger generations. | |
394 VerifyCTSpaceClosure blk(_ct, gen->reserved().start()); | |
395 gen->space_iterate(&blk, true); | |
396 } | |
397 }; | |
398 | |
399 void CardTableRS::verify_space(Space* s, HeapWord* gen_boundary) { | |
400 // We don't need to do young-gen spaces. | |
401 if (s->end() <= gen_boundary) return; | |
402 MemRegion used = s->used_region(); | |
403 | |
404 jbyte* cur_entry = byte_for(used.start()); | |
405 jbyte* limit = byte_after(used.last()); | |
406 while (cur_entry < limit) { | |
407 if (*cur_entry == CardTableModRefBS::clean_card) { | |
408 jbyte* first_dirty = cur_entry+1; | |
409 while (first_dirty < limit && | |
410 *first_dirty == CardTableModRefBS::clean_card) { | |
411 first_dirty++; | |
412 } | |
413 // If the first object is a regular object, and it has a | |
414 // young-to-old field, that would mark the previous card. | |
415 HeapWord* boundary = addr_for(cur_entry); | |
416 HeapWord* end = (first_dirty >= limit) ? used.end() : addr_for(first_dirty); | |
417 HeapWord* boundary_block = s->block_start(boundary); | |
418 HeapWord* begin = boundary; // Until proven otherwise. | |
419 HeapWord* start_block = boundary_block; // Until proven otherwise. | |
420 if (boundary_block < boundary) { | |
421 if (s->block_is_obj(boundary_block) && s->obj_is_alive(boundary_block)) { | |
422 oop boundary_obj = oop(boundary_block); | |
423 if (!boundary_obj->is_objArray() && | |
424 !boundary_obj->is_typeArray()) { | |
425 guarantee(cur_entry > byte_for(used.start()), | |
426 "else boundary would be boundary_block"); | |
427 if (*byte_for(boundary_block) != CardTableModRefBS::clean_card) { | |
428 begin = boundary_block + s->block_size(boundary_block); | |
429 start_block = begin; | |
430 } | |
431 } | |
432 } | |
433 } | |
434 // Now traverse objects until end. | |
2428
5134fa1cfe63
7029036: Card-table verification hangs with all framework collectors, except G1, even before the first GC
ysr
parents:
1972
diff
changeset
|
435 if (begin < end) { |
5134fa1cfe63
7029036: Card-table verification hangs with all framework collectors, except G1, even before the first GC
ysr
parents:
1972
diff
changeset
|
436 MemRegion mr(begin, end); |
5134fa1cfe63
7029036: Card-table verification hangs with all framework collectors, except G1, even before the first GC
ysr
parents:
1972
diff
changeset
|
437 VerifyCleanCardClosure verify_blk(gen_boundary, begin, end); |
5134fa1cfe63
7029036: Card-table verification hangs with all framework collectors, except G1, even before the first GC
ysr
parents:
1972
diff
changeset
|
438 for (HeapWord* cur = start_block; cur < end; cur += s->block_size(cur)) { |
5134fa1cfe63
7029036: Card-table verification hangs with all framework collectors, except G1, even before the first GC
ysr
parents:
1972
diff
changeset
|
439 if (s->block_is_obj(cur) && s->obj_is_alive(cur)) { |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
5939
diff
changeset
|
440 oop(cur)->oop_iterate_no_header(&verify_blk, mr); |
2428
5134fa1cfe63
7029036: Card-table verification hangs with all framework collectors, except G1, even before the first GC
ysr
parents:
1972
diff
changeset
|
441 } |
0 | 442 } |
443 } | |
444 cur_entry = first_dirty; | |
445 } else { | |
446 // We'd normally expect that cur_youngergen_and_prev_nonclean_card | |
447 // is a transient value, that cannot be in the card table | |
448 // except during GC, and thus assert that: | |
449 // guarantee(*cur_entry != cur_youngergen_and_prev_nonclean_card, | |
450 // "Illegal CT value"); | |
451 // That however, need not hold, as will become clear in the | |
452 // following... | |
453 | |
454 // We'd normally expect that if we are in the parallel case, | |
455 // we can't have left a prev value (which would be different | |
456 // from the current value) in the card table, and so we'd like to | |
457 // assert that: | |
458 // guarantee(cur_youngergen_card_val() == youngergen_card | |
459 // || !is_prev_youngergen_card_val(*cur_entry), | |
460 // "Illegal CT value"); | |
461 // That, however, may not hold occasionally, because of | |
462 // CMS or MSC in the old gen. To wit, consider the | |
463 // following two simple illustrative scenarios: | |
464 // (a) CMS: Consider the case where a large object L | |
465 // spanning several cards is allocated in the old | |
466 // gen, and has a young gen reference stored in it, dirtying | |
467 // some interior cards. A young collection scans the card, | |
468 // finds a young ref and installs a youngergenP_n value. | |
469 // L then goes dead. Now a CMS collection starts, | |
470 // finds L dead and sweeps it up. Assume that L is | |
471 // abutting _unallocated_blk, so _unallocated_blk is | |
472 // adjusted down to (below) L. Assume further that | |
473 // no young collection intervenes during this CMS cycle. | |
474 // The next young gen cycle will not get to look at this | |
475 // youngergenP_n card since it lies in the unoccupied | |
476 // part of the space. | |
477 // Some young collections later the blocks on this | |
478 // card can be re-allocated either due to direct allocation | |
479 // or due to absorbing promotions. At this time, the | |
480 // before-gc verification will fail the above assert. | |
481 // (b) MSC: In this case, an object L with a young reference | |
482 // is on a card that (therefore) holds a youngergen_n value. | |
483 // Suppose also that L lies towards the end of the used | |
484 // the used space before GC. An MSC collection | |
485 // occurs that compacts to such an extent that this | |
486 // card is no longer in the occupied part of the space. | |
487 // Since current code in MSC does not always clear cards | |
488 // in the unused part of old gen, this stale youngergen_n | |
489 // value is left behind and can later be covered by | |
490 // an object when promotion or direct allocation | |
491 // re-allocates that part of the heap. | |
492 // | |
493 // Fortunately, the presence of such stale card values is | |
494 // "only" a minor annoyance in that subsequent young collections | |
495 // might needlessly scan such cards, but would still never corrupt | |
496 // the heap as a result. However, it's likely not to be a significant | |
497 // performance inhibitor in practice. For instance, | |
498 // some recent measurements with unoccupied cards eagerly cleared | |
499 // out to maintain this invariant, showed next to no | |
500 // change in young collection times; of course one can construct | |
501 // degenerate examples where the cost can be significant.) | |
502 // Note, in particular, that if the "stale" card is modified | |
503 // after re-allocation, it would be dirty, not "stale". Thus, | |
504 // we can never have a younger ref in such a card and it is | |
505 // safe not to scan that card in any collection. [As we see | |
506 // below, we do some unnecessary scanning | |
507 // in some cases in the current parallel scanning algorithm.] | |
508 // | |
509 // The main point below is that the parallel card scanning code | |
510 // deals correctly with these stale card values. There are two main | |
511 // cases to consider where we have a stale "younger gen" value and a | |
512 // "derivative" case to consider, where we have a stale | |
513 // "cur_younger_gen_and_prev_non_clean" value, as will become | |
514 // apparent in the case analysis below. | |
515 // o Case 1. If the stale value corresponds to a younger_gen_n | |
516 // value other than the cur_younger_gen value then the code | |
517 // treats this as being tantamount to a prev_younger_gen | |
518 // card. This means that the card may be unnecessarily scanned. | |
519 // There are two sub-cases to consider: | |
520 // o Case 1a. Let us say that the card is in the occupied part | |
521 // of the generation at the time the collection begins. In | |
522 // that case the card will be either cleared when it is scanned | |
523 // for young pointers, or will be set to cur_younger_gen as a | |
524 // result of promotion. (We have elided the normal case where | |
525 // the scanning thread and the promoting thread interleave | |
526 // possibly resulting in a transient | |
527 // cur_younger_gen_and_prev_non_clean value before settling | |
528 // to cur_younger_gen. [End Case 1a.] | |
529 // o Case 1b. Consider now the case when the card is in the unoccupied | |
530 // part of the space which becomes occupied because of promotions | |
531 // into it during the current young GC. In this case the card | |
532 // will never be scanned for young references. The current | |
533 // code will set the card value to either | |
534 // cur_younger_gen_and_prev_non_clean or leave | |
535 // it with its stale value -- because the promotions didn't | |
536 // result in any younger refs on that card. Of these two | |
537 // cases, the latter will be covered in Case 1a during | |
538 // a subsequent scan. To deal with the former case, we need | |
539 // to further consider how we deal with a stale value of | |
540 // cur_younger_gen_and_prev_non_clean in our case analysis | |
541 // below. This we do in Case 3 below. [End Case 1b] | |
542 // [End Case 1] | |
543 // o Case 2. If the stale value corresponds to cur_younger_gen being | |
544 // a value not necessarily written by a current promotion, the | |
545 // card will not be scanned by the younger refs scanning code. | |
546 // (This is OK since as we argued above such cards cannot contain | |
547 // any younger refs.) The result is that this value will be | |
548 // treated as a prev_younger_gen value in a subsequent collection, | |
549 // which is addressed in Case 1 above. [End Case 2] | |
550 // o Case 3. We here consider the "derivative" case from Case 1b. above | |
551 // because of which we may find a stale | |
552 // cur_younger_gen_and_prev_non_clean card value in the table. | |
553 // Once again, as in Case 1, we consider two subcases, depending | |
554 // on whether the card lies in the occupied or unoccupied part | |
555 // of the space at the start of the young collection. | |
556 // o Case 3a. Let us say the card is in the occupied part of | |
557 // the old gen at the start of the young collection. In that | |
558 // case, the card will be scanned by the younger refs scanning | |
559 // code which will set it to cur_younger_gen. In a subsequent | |
560 // scan, the card will be considered again and get its final | |
561 // correct value. [End Case 3a] | |
562 // o Case 3b. Now consider the case where the card is in the | |
563 // unoccupied part of the old gen, and is occupied as a result | |
564 // of promotions during thus young gc. In that case, | |
565 // the card will not be scanned for younger refs. The presence | |
566 // of newly promoted objects on the card will then result in | |
567 // its keeping the value cur_younger_gen_and_prev_non_clean | |
568 // value, which we have dealt with in Case 3 here. [End Case 3b] | |
569 // [End Case 3] | |
570 // | |
571 // (Please refer to the code in the helper class | |
572 // ClearNonCleanCardWrapper and in CardTableModRefBS for details.) | |
573 // | |
574 // The informal arguments above can be tightened into a formal | |
575 // correctness proof and it behooves us to write up such a proof, | |
576 // or to use model checking to prove that there are no lingering | |
577 // concerns. | |
578 // | |
579 // Clearly because of Case 3b one cannot bound the time for | |
580 // which a card will retain what we have called a "stale" value. | |
581 // However, one can obtain a Loose upper bound on the redundant | |
582 // work as a result of such stale values. Note first that any | |
583 // time a stale card lies in the occupied part of the space at | |
584 // the start of the collection, it is scanned by younger refs | |
585 // code and we can define a rank function on card values that | |
586 // declines when this is so. Note also that when a card does not | |
587 // lie in the occupied part of the space at the beginning of a | |
588 // young collection, its rank can either decline or stay unchanged. | |
589 // In this case, no extra work is done in terms of redundant | |
590 // younger refs scanning of that card. | |
591 // Then, the case analysis above reveals that, in the worst case, | |
592 // any such stale card will be scanned unnecessarily at most twice. | |
593 // | |
594 // It is nonethelss advisable to try and get rid of some of this | |
595 // redundant work in a subsequent (low priority) re-design of | |
596 // the card-scanning code, if only to simplify the underlying | |
597 // state machine analysis/proof. ysr 1/28/2002. XXX | |
598 cur_entry++; | |
599 } | |
600 } | |
601 } | |
602 | |
603 void CardTableRS::verify() { | |
604 // At present, we only know how to verify the card table RS for | |
605 // generational heaps. | |
606 VerifyCTGenClosure blk(this); | |
607 CollectedHeap* ch = Universe::heap(); | |
608 | |
609 if (ch->kind() == CollectedHeap::GenCollectedHeap) { | |
610 GenCollectedHeap::heap()->generation_iterate(&blk, false); | |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
611 _ct_bs->verify(); |
0 | 612 } |
613 } | |
614 | |
615 | |
6
73e96e5c30df
6624765: Guarantee failure "Unexpected dirty card found"
jmasa
parents:
0
diff
changeset
|
616 void CardTableRS::verify_aligned_region_empty(MemRegion mr) { |
0 | 617 if (!mr.is_empty()) { |
618 jbyte* cur_entry = byte_for(mr.start()); | |
619 jbyte* limit = byte_after(mr.last()); | |
6
73e96e5c30df
6624765: Guarantee failure "Unexpected dirty card found"
jmasa
parents:
0
diff
changeset
|
620 // The region mr may not start on a card boundary so |
73e96e5c30df
6624765: Guarantee failure "Unexpected dirty card found"
jmasa
parents:
0
diff
changeset
|
621 // the first card may reflect a write to the space |
73e96e5c30df
6624765: Guarantee failure "Unexpected dirty card found"
jmasa
parents:
0
diff
changeset
|
622 // just prior to mr. |
73e96e5c30df
6624765: Guarantee failure "Unexpected dirty card found"
jmasa
parents:
0
diff
changeset
|
623 if (!is_aligned(mr.start())) { |
73e96e5c30df
6624765: Guarantee failure "Unexpected dirty card found"
jmasa
parents:
0
diff
changeset
|
624 cur_entry++; |
73e96e5c30df
6624765: Guarantee failure "Unexpected dirty card found"
jmasa
parents:
0
diff
changeset
|
625 } |
0 | 626 for (;cur_entry < limit; cur_entry++) { |
627 guarantee(*cur_entry == CardTableModRefBS::clean_card, | |
628 "Unexpected dirty card found"); | |
629 } | |
630 } | |
631 } |