1 /*
2 * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
156 "We shouldn't be looking at clean cards, and this should "
157 "be the only place they get cleaned.");
158 assert(entry_val != CardTableRS::cur_youngergen_and_prev_nonclean_card,
159 "This should be possible in the sequential case.");
160 *entry = CardTableRS::clean_card_val();
161 return true;
162 }
163
164 ClearNoncleanCardWrapper::ClearNoncleanCardWrapper(
165 DirtyCardToOopClosure* dirty_card_closure, CardTableRS* ct) :
166 _dirty_card_closure(dirty_card_closure), _ct(ct) {
167 // Cannot yet substitute active_workers for n_par_threads
168 // in the case where parallelism is being turned off by
169 // setting n_par_threads to 0.
170 _is_par = (SharedHeap::heap()->n_par_threads() > 0);
171 assert(!_is_par ||
172 (SharedHeap::heap()->n_par_threads() ==
173 SharedHeap::heap()->workers()->active_workers()), "Mismatch");
174 }
175
176 void ClearNoncleanCardWrapper::do_MemRegion(MemRegion mr) {
177 assert(mr.word_size() > 0, "Error");
178 assert(_ct->is_aligned(mr.start()), "mr.start() should be card aligned");
179 // mr.end() may not necessarily be card aligned.
180 jbyte* cur_entry = _ct->byte_for(mr.last());
181 const jbyte* limit = _ct->byte_for(mr.start());
182 HeapWord* end_of_non_clean = mr.end();
183 HeapWord* start_of_non_clean = end_of_non_clean;
184 while (cur_entry >= limit) {
185 HeapWord* cur_hw = _ct->addr_for(cur_entry);
186 if ((*cur_entry != CardTableRS::clean_card_val()) && clear_card(cur_entry)) {
187 // Continue the dirty range by opening the
188 // dirty window one card to the left.
189 start_of_non_clean = cur_hw;
190 } else {
191 // We hit a "clean" card; process any non-empty
192 // "dirty" range accumulated so far.
193 if (start_of_non_clean < end_of_non_clean) {
194 const MemRegion mrd(start_of_non_clean, end_of_non_clean);
195 _dirty_card_closure->do_MemRegion(mrd);
196 }
197 // Reset the dirty window, while continuing to look
198 // for the next dirty card that will start a
199 // new dirty window.
200 end_of_non_clean = cur_hw;
201 start_of_non_clean = cur_hw;
202 }
203 // Note that "cur_entry" leads "start_of_non_clean" in
204 // its leftward excursion after this point
205 // in the loop and, when we hit the left end of "mr",
206 // will point off of the left end of the card-table
207 // for "mr".
208 cur_entry--;
209 }
210 // If the first card of "mr" was dirty, we will have
211 // been left with a dirty window, co-initial with "mr",
212 // which we now process.
213 if (start_of_non_clean < end_of_non_clean) {
214 const MemRegion mrd(start_of_non_clean, end_of_non_clean);
215 _dirty_card_closure->do_MemRegion(mrd);
216 }
217 }
218
219 // clean (by dirty->clean before) ==> cur_younger_gen
220 // dirty ==> cur_youngergen_and_prev_nonclean_card
221 // precleaned ==> cur_youngergen_and_prev_nonclean_card
222 // prev-younger-gen ==> cur_youngergen_and_prev_nonclean_card
223 // cur-younger-gen ==> cur_younger_gen
224 // cur_youngergen_and_prev_nonclean_card ==> no change.
225 void CardTableRS::write_ref_field_gc_par(void* field, oop new_val) {
226 jbyte* entry = ct_bs()->byte_for(field);
227 do {
228 jbyte entry_val = *entry;
|
1 /*
2 * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
156 "We shouldn't be looking at clean cards, and this should "
157 "be the only place they get cleaned.");
158 assert(entry_val != CardTableRS::cur_youngergen_and_prev_nonclean_card,
159 "This should be possible in the sequential case.");
160 *entry = CardTableRS::clean_card_val();
161 return true;
162 }
163
164 ClearNoncleanCardWrapper::ClearNoncleanCardWrapper(
165 DirtyCardToOopClosure* dirty_card_closure, CardTableRS* ct) :
166 _dirty_card_closure(dirty_card_closure), _ct(ct) {
167 // Cannot yet substitute active_workers for n_par_threads
168 // in the case where parallelism is being turned off by
169 // setting n_par_threads to 0.
170 _is_par = (SharedHeap::heap()->n_par_threads() > 0);
171 assert(!_is_par ||
172 (SharedHeap::heap()->n_par_threads() ==
173 SharedHeap::heap()->workers()->active_workers()), "Mismatch");
174 }
175
176 bool ClearNoncleanCardWrapper::is_word_aligned(jbyte* entry) {
177 return (((intptr_t)entry) & (BytesPerWord-1)) == 0;
178 }
179
180 void ClearNoncleanCardWrapper::do_MemRegion(MemRegion mr) {
181 assert(mr.word_size() > 0, "Error");
182 assert(_ct->is_aligned(mr.start()), "mr.start() should be card aligned");
183 // mr.end() may not necessarily be card aligned.
184 jbyte* cur_entry = _ct->byte_for(mr.last());
185 const jbyte* limit = _ct->byte_for(mr.start());
186 HeapWord* end_of_non_clean = mr.end();
187 HeapWord* start_of_non_clean = end_of_non_clean;
188 while (cur_entry >= limit) {
189 HeapWord* cur_hw = _ct->addr_for(cur_entry);
190 if ((*cur_entry != CardTableRS::clean_card_val()) && clear_card(cur_entry)) {
191 // Continue the dirty range by opening the
192 // dirty window one card to the left.
193 start_of_non_clean = cur_hw;
194
195 cur_entry--;
196 } else {
197 // We hit a "clean" card; process any non-empty
198 // "dirty" range accumulated so far.
199 if (start_of_non_clean < end_of_non_clean) {
200 const MemRegion mrd(start_of_non_clean, end_of_non_clean);
201 _dirty_card_closure->do_MemRegion(mrd);
202 }
203
204 // fast forward through potential continuous range of clean cards
205 if (is_word_aligned(cur_entry)) {
206 jbyte* cur_row = cur_entry - BytesPerWord;
207 while(cur_row >= limit) {
208 if (*((intptr_t*)cur_row) == CardTableRS::clean_card_row()) {
209 cur_row -= BytesPerWord;
210 }
211 else {
212 break;
213 }
214 }
215 cur_entry = cur_row + (BytesPerWord - 1);
216 HeapWord* last_hw = _ct->addr_for(cur_row + BytesPerWord);
217 end_of_non_clean = last_hw;
218 start_of_non_clean = last_hw;
219 } else {
220 // Reset the dirty window, while continuing to look
221 // for the next dirty card that will start a
222 // new dirty window.
223 end_of_non_clean = cur_hw;
224 start_of_non_clean = cur_hw;
225 cur_entry--;
226 }
227 }
228 // Note that "cur_entry" leads "start_of_non_clean" in
229 // its leftward excursion after this point
230 // in the loop and, when we hit the left end of "mr",
231 // will point off of the left end of the card-table
232 // for "mr".
233 }
234 // If the first card of "mr" was dirty, we will have
235 // been left with a dirty window, co-initial with "mr",
236 // which we now process.
237 if (start_of_non_clean < end_of_non_clean) {
238 const MemRegion mrd(start_of_non_clean, end_of_non_clean);
239 _dirty_card_closure->do_MemRegion(mrd);
240 }
241 }
242
243 // clean (by dirty->clean before) ==> cur_younger_gen
244 // dirty ==> cur_youngergen_and_prev_nonclean_card
245 // precleaned ==> cur_youngergen_and_prev_nonclean_card
246 // prev-younger-gen ==> cur_youngergen_and_prev_nonclean_card
247 // cur-younger-gen ==> cur_younger_gen
248 // cur_youngergen_and_prev_nonclean_card ==> no change.
249 void CardTableRS::write_ref_field_gc_par(void* field, oop new_val) {
250 jbyte* entry = ct_bs()->byte_for(field);
251 do {
252 jbyte entry_val = *entry;
|