Mercurial > hg > graal-jvmci-8
annotate src/share/vm/gc_implementation/g1/g1BlockOffsetTable.cpp @ 1974:fd1d227ef1b9
6983204: G1: Nightly test nsk/regression/b4958615 failing with +ExplicitGCInvokesConcurrent
Summary: Enable reference discovery during concurrent marking by setting the reference processor field of the concurrent marking closure. Keep reference objects on the discovered reference lists alive during incremental evacuation pauses until they are processed at the end of concurrent marking.
Reviewed-by: ysr, tonyp
author | johnc |
---|---|
date | Wed, 01 Dec 2010 17:34:02 -0800 |
parents | f95d63e2154a |
children | 2250ee17e258 |
rev | line source |
---|---|
342 | 1 /* |
1972 | 2 * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. |
342 | 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:
1489
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1489
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:
1489
diff
changeset
|
21 * questions. |
342 | 22 * |
23 */ | |
24 | |
1972 | 25 #include "precompiled.hpp" |
26 #include "gc_implementation/g1/g1BlockOffsetTable.inline.hpp" | |
27 #include "memory/space.hpp" | |
28 #include "oops/oop.inline.hpp" | |
29 #include "runtime/java.hpp" | |
342 | 30 |
31 ////////////////////////////////////////////////////////////////////// | |
32 // G1BlockOffsetSharedArray | |
33 ////////////////////////////////////////////////////////////////////// | |
34 | |
35 G1BlockOffsetSharedArray::G1BlockOffsetSharedArray(MemRegion reserved, | |
36 size_t init_word_size) : | |
37 _reserved(reserved), _end(NULL) | |
38 { | |
39 size_t size = compute_size(reserved.word_size()); | |
40 ReservedSpace rs(ReservedSpace::allocation_align_size_up(size)); | |
41 if (!rs.is_reserved()) { | |
42 vm_exit_during_initialization("Could not reserve enough space for heap offset array"); | |
43 } | |
44 if (!_vs.initialize(rs, 0)) { | |
45 vm_exit_during_initialization("Could not reserve enough space for heap offset array"); | |
46 } | |
47 _offset_array = (u_char*)_vs.low_boundary(); | |
48 resize(init_word_size); | |
49 if (TraceBlockOffsetTable) { | |
50 gclog_or_tty->print_cr("G1BlockOffsetSharedArray::G1BlockOffsetSharedArray: "); | |
51 gclog_or_tty->print_cr(" " | |
52 " rs.base(): " INTPTR_FORMAT | |
53 " rs.size(): " INTPTR_FORMAT | |
54 " rs end(): " INTPTR_FORMAT, | |
55 rs.base(), rs.size(), rs.base() + rs.size()); | |
56 gclog_or_tty->print_cr(" " | |
57 " _vs.low_boundary(): " INTPTR_FORMAT | |
58 " _vs.high_boundary(): " INTPTR_FORMAT, | |
59 _vs.low_boundary(), | |
60 _vs.high_boundary()); | |
61 } | |
62 } | |
63 | |
64 void G1BlockOffsetSharedArray::resize(size_t new_word_size) { | |
65 assert(new_word_size <= _reserved.word_size(), "Resize larger than reserved"); | |
66 size_t new_size = compute_size(new_word_size); | |
67 size_t old_size = _vs.committed_size(); | |
68 size_t delta; | |
69 char* high = _vs.high(); | |
70 _end = _reserved.start() + new_word_size; | |
71 if (new_size > old_size) { | |
72 delta = ReservedSpace::page_align_size_up(new_size - old_size); | |
73 assert(delta > 0, "just checking"); | |
74 if (!_vs.expand_by(delta)) { | |
75 // Do better than this for Merlin | |
76 vm_exit_out_of_memory(delta, "offset table expansion"); | |
77 } | |
78 assert(_vs.high() == high + delta, "invalid expansion"); | |
79 // Initialization of the contents is left to the | |
80 // G1BlockOffsetArray that uses it. | |
81 } else { | |
82 delta = ReservedSpace::page_align_size_down(old_size - new_size); | |
83 if (delta == 0) return; | |
84 _vs.shrink_by(delta); | |
85 assert(_vs.high() == high - delta, "invalid expansion"); | |
86 } | |
87 } | |
88 | |
89 bool G1BlockOffsetSharedArray::is_card_boundary(HeapWord* p) const { | |
90 assert(p >= _reserved.start(), "just checking"); | |
91 size_t delta = pointer_delta(p, _reserved.start()); | |
92 return (delta & right_n_bits(LogN_words)) == (size_t)NoBits; | |
93 } | |
94 | |
95 | |
96 ////////////////////////////////////////////////////////////////////// | |
97 // G1BlockOffsetArray | |
98 ////////////////////////////////////////////////////////////////////// | |
99 | |
100 G1BlockOffsetArray::G1BlockOffsetArray(G1BlockOffsetSharedArray* array, | |
101 MemRegion mr, bool init_to_zero) : | |
102 G1BlockOffsetTable(mr.start(), mr.end()), | |
103 _unallocated_block(_bottom), | |
104 _array(array), _csp(NULL), | |
105 _init_to_zero(init_to_zero) { | |
106 assert(_bottom <= _end, "arguments out of order"); | |
107 if (!_init_to_zero) { | |
108 // initialize cards to point back to mr.start() | |
109 set_remainder_to_point_to_start(mr.start() + N_words, mr.end()); | |
110 _array->set_offset_array(0, 0); // set first card to 0 | |
111 } | |
112 } | |
113 | |
114 void G1BlockOffsetArray::set_space(Space* sp) { | |
115 _sp = sp; | |
116 _csp = sp->toContiguousSpace(); | |
117 } | |
118 | |
119 // The arguments follow the normal convention of denoting | |
120 // a right-open interval: [start, end) | |
121 void | |
122 G1BlockOffsetArray:: set_remainder_to_point_to_start(HeapWord* start, HeapWord* end) { | |
123 | |
124 if (start >= end) { | |
125 // The start address is equal to the end address (or to | |
126 // the right of the end address) so there are not cards | |
127 // that need to be updated.. | |
128 return; | |
129 } | |
130 | |
131 // Write the backskip value for each region. | |
132 // | |
133 // offset | |
134 // card 2nd 3rd | |
135 // | +- 1st | | | |
136 // v v v v | |
137 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+- | |
138 // |x|0|0|0|0|0|0|0|1|1|1|1|1|1| ... |1|1|1|1|2|2|2|2|2|2| ... | |
139 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+- | |
140 // 11 19 75 | |
141 // 12 | |
142 // | |
143 // offset card is the card that points to the start of an object | |
144 // x - offset value of offset card | |
145 // 1st - start of first logarithmic region | |
146 // 0 corresponds to logarithmic value N_words + 0 and 2**(3 * 0) = 1 | |
147 // 2nd - start of second logarithmic region | |
148 // 1 corresponds to logarithmic value N_words + 1 and 2**(3 * 1) = 8 | |
149 // 3rd - start of third logarithmic region | |
150 // 2 corresponds to logarithmic value N_words + 2 and 2**(3 * 2) = 64 | |
151 // | |
152 // integer below the block offset entry is an example of | |
153 // the index of the entry | |
154 // | |
155 // Given an address, | |
156 // Find the index for the address | |
157 // Find the block offset table entry | |
158 // Convert the entry to a back slide | |
159 // (e.g., with today's, offset = 0x81 => | |
160 // back slip = 2**(3*(0x81 - N_words)) = 2**3) = 8 | |
161 // Move back N (e.g., 8) entries and repeat with the | |
162 // value of the new entry | |
163 // | |
164 size_t start_card = _array->index_for(start); | |
165 size_t end_card = _array->index_for(end-1); | |
166 assert(start ==_array->address_for_index(start_card), "Precondition"); | |
167 assert(end ==_array->address_for_index(end_card)+N_words, "Precondition"); | |
168 set_remainder_to_point_to_start_incl(start_card, end_card); // closed interval | |
169 } | |
170 | |
171 // Unlike the normal convention in this code, the argument here denotes | |
172 // a closed, inclusive interval: [start_card, end_card], cf set_remainder_to_point_to_start() | |
173 // above. | |
174 void | |
175 G1BlockOffsetArray::set_remainder_to_point_to_start_incl(size_t start_card, size_t end_card) { | |
176 if (start_card > end_card) { | |
177 return; | |
178 } | |
179 assert(start_card > _array->index_for(_bottom), "Cannot be first card"); | |
180 assert(_array->offset_array(start_card-1) <= N_words, | |
1886
72a161e62cc4
6991377: G1: race between concurrent refinement and humongous object allocation
tonyp
parents:
1552
diff
changeset
|
181 "Offset card has an unexpected value"); |
342 | 182 size_t start_card_for_region = start_card; |
183 u_char offset = max_jubyte; | |
184 for (int i = 0; i < BlockOffsetArray::N_powers; i++) { | |
185 // -1 so that the the card with the actual offset is counted. Another -1 | |
186 // so that the reach ends in this region and not at the start | |
187 // of the next. | |
188 size_t reach = start_card - 1 + (BlockOffsetArray::power_to_cards_back(i+1) - 1); | |
189 offset = N_words + i; | |
190 if (reach >= end_card) { | |
191 _array->set_offset_array(start_card_for_region, end_card, offset); | |
192 start_card_for_region = reach + 1; | |
193 break; | |
194 } | |
195 _array->set_offset_array(start_card_for_region, reach, offset); | |
196 start_card_for_region = reach + 1; | |
197 } | |
198 assert(start_card_for_region > end_card, "Sanity check"); | |
199 DEBUG_ONLY(check_all_cards(start_card, end_card);) | |
200 } | |
201 | |
202 // The block [blk_start, blk_end) has been allocated; | |
203 // adjust the block offset table to represent this information; | |
204 // right-open interval: [blk_start, blk_end) | |
205 void | |
206 G1BlockOffsetArray::alloc_block(HeapWord* blk_start, HeapWord* blk_end) { | |
207 mark_block(blk_start, blk_end); | |
208 allocated(blk_start, blk_end); | |
209 } | |
210 | |
211 // Adjust BOT to show that a previously whole block has been split | |
212 // into two. | |
213 void G1BlockOffsetArray::split_block(HeapWord* blk, size_t blk_size, | |
214 size_t left_blk_size) { | |
215 // Verify that the BOT shows [blk, blk + blk_size) to be one block. | |
216 verify_single_block(blk, blk_size); | |
217 // Update the BOT to indicate that [blk + left_blk_size, blk + blk_size) | |
218 // is one single block. | |
219 mark_block(blk + left_blk_size, blk + blk_size); | |
220 } | |
221 | |
222 | |
223 // Action_mark - update the BOT for the block [blk_start, blk_end). | |
224 // Current typical use is for splitting a block. | |
225 // Action_single - udpate the BOT for an allocation. | |
226 // Action_verify - BOT verification. | |
227 void G1BlockOffsetArray::do_block_internal(HeapWord* blk_start, | |
228 HeapWord* blk_end, | |
229 Action action) { | |
230 assert(Universe::heap()->is_in_reserved(blk_start), | |
231 "reference must be into the heap"); | |
232 assert(Universe::heap()->is_in_reserved(blk_end-1), | |
233 "limit must be within the heap"); | |
234 // This is optimized to make the test fast, assuming we only rarely | |
235 // cross boundaries. | |
236 uintptr_t end_ui = (uintptr_t)(blk_end - 1); | |
237 uintptr_t start_ui = (uintptr_t)blk_start; | |
238 // Calculate the last card boundary preceding end of blk | |
239 intptr_t boundary_before_end = (intptr_t)end_ui; | |
240 clear_bits(boundary_before_end, right_n_bits(LogN)); | |
241 if (start_ui <= (uintptr_t)boundary_before_end) { | |
242 // blk starts at or crosses a boundary | |
243 // Calculate index of card on which blk begins | |
244 size_t start_index = _array->index_for(blk_start); | |
245 // Index of card on which blk ends | |
246 size_t end_index = _array->index_for(blk_end - 1); | |
247 // Start address of card on which blk begins | |
248 HeapWord* boundary = _array->address_for_index(start_index); | |
249 assert(boundary <= blk_start, "blk should start at or after boundary"); | |
250 if (blk_start != boundary) { | |
251 // blk starts strictly after boundary | |
252 // adjust card boundary and start_index forward to next card | |
253 boundary += N_words; | |
254 start_index++; | |
255 } | |
256 assert(start_index <= end_index, "monotonicity of index_for()"); | |
257 assert(boundary <= (HeapWord*)boundary_before_end, "tautology"); | |
258 switch (action) { | |
259 case Action_mark: { | |
260 if (init_to_zero()) { | |
261 _array->set_offset_array(start_index, boundary, blk_start); | |
262 break; | |
263 } // Else fall through to the next case | |
264 } | |
265 case Action_single: { | |
266 _array->set_offset_array(start_index, boundary, blk_start); | |
267 // We have finished marking the "offset card". We need to now | |
268 // mark the subsequent cards that this blk spans. | |
269 if (start_index < end_index) { | |
270 HeapWord* rem_st = _array->address_for_index(start_index) + N_words; | |
271 HeapWord* rem_end = _array->address_for_index(end_index) + N_words; | |
272 set_remainder_to_point_to_start(rem_st, rem_end); | |
273 } | |
274 break; | |
275 } | |
276 case Action_check: { | |
277 _array->check_offset_array(start_index, boundary, blk_start); | |
278 // We have finished checking the "offset card". We need to now | |
279 // check the subsequent cards that this blk spans. | |
280 check_all_cards(start_index + 1, end_index); | |
281 break; | |
282 } | |
283 default: | |
284 ShouldNotReachHere(); | |
285 } | |
286 } | |
287 } | |
288 | |
289 // The card-interval [start_card, end_card] is a closed interval; this | |
290 // is an expensive check -- use with care and only under protection of | |
291 // suitable flag. | |
292 void G1BlockOffsetArray::check_all_cards(size_t start_card, size_t end_card) const { | |
293 | |
294 if (end_card < start_card) { | |
295 return; | |
296 } | |
297 guarantee(_array->offset_array(start_card) == N_words, "Wrong value in second card"); | |
298 for (size_t c = start_card + 1; c <= end_card; c++ /* yeah! */) { | |
299 u_char entry = _array->offset_array(c); | |
300 if (c - start_card > BlockOffsetArray::power_to_cards_back(1)) { | |
301 guarantee(entry > N_words, "Should be in logarithmic region"); | |
302 } | |
303 size_t backskip = BlockOffsetArray::entry_to_cards_back(entry); | |
304 size_t landing_card = c - backskip; | |
305 guarantee(landing_card >= (start_card - 1), "Inv"); | |
306 if (landing_card >= start_card) { | |
307 guarantee(_array->offset_array(landing_card) <= entry, "monotonicity"); | |
308 } else { | |
309 guarantee(landing_card == start_card - 1, "Tautology"); | |
310 guarantee(_array->offset_array(landing_card) <= N_words, "Offset value"); | |
311 } | |
312 } | |
313 } | |
314 | |
315 // The range [blk_start, blk_end) represents a single contiguous block | |
316 // of storage; modify the block offset table to represent this | |
317 // information; Right-open interval: [blk_start, blk_end) | |
318 // NOTE: this method does _not_ adjust _unallocated_block. | |
319 void | |
320 G1BlockOffsetArray::single_block(HeapWord* blk_start, HeapWord* blk_end) { | |
321 do_block_internal(blk_start, blk_end, Action_single); | |
322 } | |
323 | |
324 // Mark the BOT such that if [blk_start, blk_end) straddles a card | |
325 // boundary, the card following the first such boundary is marked | |
326 // with the appropriate offset. | |
327 // NOTE: this method does _not_ adjust _unallocated_block or | |
328 // any cards subsequent to the first one. | |
329 void | |
330 G1BlockOffsetArray::mark_block(HeapWord* blk_start, HeapWord* blk_end) { | |
331 do_block_internal(blk_start, blk_end, Action_mark); | |
332 } | |
333 | |
334 void G1BlockOffsetArray::join_blocks(HeapWord* blk1, HeapWord* blk2) { | |
335 HeapWord* blk1_start = Universe::heap()->block_start(blk1); | |
336 HeapWord* blk2_start = Universe::heap()->block_start(blk2); | |
337 assert(blk1 == blk1_start && blk2 == blk2_start, | |
338 "Must be block starts."); | |
339 assert(blk1 + _sp->block_size(blk1) == blk2, "Must be contiguous."); | |
340 size_t blk1_start_index = _array->index_for(blk1); | |
341 size_t blk2_start_index = _array->index_for(blk2); | |
342 assert(blk1_start_index <= blk2_start_index, "sanity"); | |
343 HeapWord* blk2_card_start = _array->address_for_index(blk2_start_index); | |
344 if (blk2 == blk2_card_start) { | |
345 // blk2 starts a card. Does blk1 start on the prevous card, or futher | |
346 // back? | |
347 assert(blk1_start_index < blk2_start_index, "must be lower card."); | |
348 if (blk1_start_index + 1 == blk2_start_index) { | |
349 // previous card; new value for blk2 card is size of blk1. | |
350 _array->set_offset_array(blk2_start_index, (u_char) _sp->block_size(blk1)); | |
351 } else { | |
352 // Earlier card; go back a card. | |
353 _array->set_offset_array(blk2_start_index, N_words); | |
354 } | |
355 } else { | |
356 // blk2 does not start a card. Does it cross a card? If not, nothing | |
357 // to do. | |
358 size_t blk2_end_index = | |
359 _array->index_for(blk2 + _sp->block_size(blk2) - 1); | |
360 assert(blk2_end_index >= blk2_start_index, "sanity"); | |
361 if (blk2_end_index > blk2_start_index) { | |
362 // Yes, it crosses a card. The value for the next card must change. | |
363 if (blk1_start_index + 1 == blk2_start_index) { | |
364 // previous card; new value for second blk2 card is size of blk1. | |
365 _array->set_offset_array(blk2_start_index + 1, | |
366 (u_char) _sp->block_size(blk1)); | |
367 } else { | |
368 // Earlier card; go back a card. | |
369 _array->set_offset_array(blk2_start_index + 1, N_words); | |
370 } | |
371 } | |
372 } | |
373 } | |
374 | |
375 HeapWord* G1BlockOffsetArray::block_start_unsafe(const void* addr) { | |
376 assert(_bottom <= addr && addr < _end, | |
377 "addr must be covered by this Array"); | |
378 // Must read this exactly once because it can be modified by parallel | |
379 // allocation. | |
380 HeapWord* ub = _unallocated_block; | |
381 if (BlockOffsetArrayUseUnallocatedBlock && addr >= ub) { | |
382 assert(ub < _end, "tautology (see above)"); | |
383 return ub; | |
384 } | |
385 // Otherwise, find the block start using the table. | |
386 HeapWord* q = block_at_or_preceding(addr, false, 0); | |
387 return forward_to_block_containing_addr(q, addr); | |
388 } | |
389 | |
390 // This duplicates a little code from the above: unavoidable. | |
391 HeapWord* | |
392 G1BlockOffsetArray::block_start_unsafe_const(const void* addr) const { | |
393 assert(_bottom <= addr && addr < _end, | |
394 "addr must be covered by this Array"); | |
395 // Must read this exactly once because it can be modified by parallel | |
396 // allocation. | |
397 HeapWord* ub = _unallocated_block; | |
398 if (BlockOffsetArrayUseUnallocatedBlock && addr >= ub) { | |
399 assert(ub < _end, "tautology (see above)"); | |
400 return ub; | |
401 } | |
402 // Otherwise, find the block start using the table. | |
403 HeapWord* q = block_at_or_preceding(addr, false, 0); | |
404 HeapWord* n = q + _sp->block_size(q); | |
405 return forward_to_block_containing_addr_const(q, n, addr); | |
406 } | |
407 | |
408 | |
409 HeapWord* | |
410 G1BlockOffsetArray::forward_to_block_containing_addr_slow(HeapWord* q, | |
411 HeapWord* n, | |
412 const void* addr) { | |
413 // We're not in the normal case. We need to handle an important subcase | |
414 // here: LAB allocation. An allocation previously recorded in the | |
415 // offset table was actually a lab allocation, and was divided into | |
416 // several objects subsequently. Fix this situation as we answer the | |
417 // query, by updating entries as we cross them. | |
352
e0c09f7ec5c4
6702387: G1: assertion failure: assert(p == current_top || oop(p)->is_oop(),"p is not a block start")
iveresov
parents:
342
diff
changeset
|
418 |
e0c09f7ec5c4
6702387: G1: assertion failure: assert(p == current_top || oop(p)->is_oop(),"p is not a block start")
iveresov
parents:
342
diff
changeset
|
419 // If the fist object's end q is at the card boundary. Start refining |
e0c09f7ec5c4
6702387: G1: assertion failure: assert(p == current_top || oop(p)->is_oop(),"p is not a block start")
iveresov
parents:
342
diff
changeset
|
420 // with the corresponding card (the value of the entry will be basically |
e0c09f7ec5c4
6702387: G1: assertion failure: assert(p == current_top || oop(p)->is_oop(),"p is not a block start")
iveresov
parents:
342
diff
changeset
|
421 // set to 0). If the object crosses the boundary -- start from the next card. |
e0c09f7ec5c4
6702387: G1: assertion failure: assert(p == current_top || oop(p)->is_oop(),"p is not a block start")
iveresov
parents:
342
diff
changeset
|
422 size_t next_index = _array->index_for(n) + !_array->is_card_boundary(n); |
342 | 423 HeapWord* next_boundary = _array->address_for_index(next_index); |
424 if (csp() != NULL) { | |
425 if (addr >= csp()->top()) return csp()->top(); | |
426 while (next_boundary < addr) { | |
427 while (n <= next_boundary) { | |
428 q = n; | |
429 oop obj = oop(q); | |
845
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
470
diff
changeset
|
430 if (obj->klass_or_null() == NULL) return q; |
342 | 431 n += obj->size(); |
432 } | |
433 assert(q <= next_boundary && n > next_boundary, "Consequence of loop"); | |
434 // [q, n) is the block that crosses the boundary. | |
435 alloc_block_work2(&next_boundary, &next_index, q, n); | |
436 } | |
437 } else { | |
438 while (next_boundary < addr) { | |
439 while (n <= next_boundary) { | |
440 q = n; | |
441 oop obj = oop(q); | |
845
df6caf649ff7
6700789: G1: Enable use of compressed oops with G1 heaps
ysr
parents:
470
diff
changeset
|
442 if (obj->klass_or_null() == NULL) return q; |
342 | 443 n += _sp->block_size(q); |
444 } | |
445 assert(q <= next_boundary && n > next_boundary, "Consequence of loop"); | |
446 // [q, n) is the block that crosses the boundary. | |
447 alloc_block_work2(&next_boundary, &next_index, q, n); | |
448 } | |
449 } | |
450 return forward_to_block_containing_addr_const(q, n, addr); | |
451 } | |
452 | |
453 HeapWord* G1BlockOffsetArray::block_start_careful(const void* addr) const { | |
454 assert(_array->offset_array(0) == 0, "objects can't cross covered areas"); | |
455 | |
456 assert(_bottom <= addr && addr < _end, | |
457 "addr must be covered by this Array"); | |
458 // Must read this exactly once because it can be modified by parallel | |
459 // allocation. | |
460 HeapWord* ub = _unallocated_block; | |
461 if (BlockOffsetArrayUseUnallocatedBlock && addr >= ub) { | |
462 assert(ub < _end, "tautology (see above)"); | |
463 return ub; | |
464 } | |
465 | |
466 // Otherwise, find the block start using the table, but taking | |
467 // care (cf block_start_unsafe() above) not to parse any objects/blocks | |
468 // on the cards themsleves. | |
469 size_t index = _array->index_for(addr); | |
470 assert(_array->address_for_index(index) == addr, | |
471 "arg should be start of card"); | |
472 | |
473 HeapWord* q = (HeapWord*)addr; | |
474 uint offset; | |
475 do { | |
476 offset = _array->offset_array(index--); | |
477 q -= offset; | |
478 } while (offset == N_words); | |
479 assert(q <= addr, "block start should be to left of arg"); | |
480 return q; | |
481 } | |
482 | |
483 // Note that the committed size of the covered space may have changed, | |
484 // so the table size might also wish to change. | |
485 void G1BlockOffsetArray::resize(size_t new_word_size) { | |
486 HeapWord* new_end = _bottom + new_word_size; | |
487 if (_end < new_end && !init_to_zero()) { | |
488 // verify that the old and new boundaries are also card boundaries | |
489 assert(_array->is_card_boundary(_end), | |
490 "_end not a card boundary"); | |
491 assert(_array->is_card_boundary(new_end), | |
492 "new _end would not be a card boundary"); | |
493 // set all the newly added cards | |
494 _array->set_offset_array(_end, new_end, N_words); | |
495 } | |
496 _end = new_end; // update _end | |
497 } | |
498 | |
499 void G1BlockOffsetArray::set_region(MemRegion mr) { | |
500 _bottom = mr.start(); | |
501 _end = mr.end(); | |
502 } | |
503 | |
504 // | |
505 // threshold_ | |
506 // | _index_ | |
507 // v v | |
508 // +-------+-------+-------+-------+-------+ | |
509 // | i-1 | i | i+1 | i+2 | i+3 | | |
510 // +-------+-------+-------+-------+-------+ | |
511 // ( ^ ] | |
512 // block-start | |
513 // | |
514 void G1BlockOffsetArray::alloc_block_work2(HeapWord** threshold_, size_t* index_, | |
515 HeapWord* blk_start, HeapWord* blk_end) { | |
516 // For efficiency, do copy-in/copy-out. | |
517 HeapWord* threshold = *threshold_; | |
518 size_t index = *index_; | |
519 | |
520 assert(blk_start != NULL && blk_end > blk_start, | |
521 "phantom block"); | |
522 assert(blk_end > threshold, "should be past threshold"); | |
1489
cff162798819
6888953: some calls to function-like macros are missing semicolons
jcoomes
parents:
845
diff
changeset
|
523 assert(blk_start <= threshold, "blk_start should be at or before threshold"); |
342 | 524 assert(pointer_delta(threshold, blk_start) <= N_words, |
525 "offset should be <= BlockOffsetSharedArray::N"); | |
526 assert(Universe::heap()->is_in_reserved(blk_start), | |
527 "reference must be into the heap"); | |
528 assert(Universe::heap()->is_in_reserved(blk_end-1), | |
529 "limit must be within the heap"); | |
530 assert(threshold == _array->_reserved.start() + index*N_words, | |
531 "index must agree with threshold"); | |
532 | |
533 DEBUG_ONLY(size_t orig_index = index;) | |
534 | |
535 // Mark the card that holds the offset into the block. Note | |
536 // that _next_offset_index and _next_offset_threshold are not | |
537 // updated until the end of this method. | |
538 _array->set_offset_array(index, threshold, blk_start); | |
539 | |
540 // We need to now mark the subsequent cards that this blk spans. | |
541 | |
542 // Index of card on which blk ends. | |
543 size_t end_index = _array->index_for(blk_end - 1); | |
544 | |
545 // Are there more cards left to be updated? | |
546 if (index + 1 <= end_index) { | |
547 HeapWord* rem_st = _array->address_for_index(index + 1); | |
548 // Calculate rem_end this way because end_index | |
549 // may be the last valid index in the covered region. | |
550 HeapWord* rem_end = _array->address_for_index(end_index) + N_words; | |
551 set_remainder_to_point_to_start(rem_st, rem_end); | |
552 } | |
553 | |
554 index = end_index + 1; | |
555 // Calculate threshold_ this way because end_index | |
556 // may be the last valid index in the covered region. | |
557 threshold = _array->address_for_index(end_index) + N_words; | |
558 assert(threshold >= blk_end, "Incorrect offset threshold"); | |
559 | |
560 // index_ and threshold_ updated here. | |
561 *threshold_ = threshold; | |
562 *index_ = index; | |
563 | |
564 #ifdef ASSERT | |
565 // The offset can be 0 if the block starts on a boundary. That | |
566 // is checked by an assertion above. | |
567 size_t start_index = _array->index_for(blk_start); | |
568 HeapWord* boundary = _array->address_for_index(start_index); | |
569 assert((_array->offset_array(orig_index) == 0 && | |
570 blk_start == boundary) || | |
571 (_array->offset_array(orig_index) > 0 && | |
572 _array->offset_array(orig_index) <= N_words), | |
573 "offset array should have been set"); | |
574 for (size_t j = orig_index + 1; j <= end_index; j++) { | |
575 assert(_array->offset_array(j) > 0 && | |
576 _array->offset_array(j) <= | |
577 (u_char) (N_words+BlockOffsetArray::N_powers-1), | |
578 "offset array should have been set"); | |
579 } | |
580 #endif | |
581 } | |
582 | |
1886
72a161e62cc4
6991377: G1: race between concurrent refinement and humongous object allocation
tonyp
parents:
1552
diff
changeset
|
583 void |
72a161e62cc4
6991377: G1: race between concurrent refinement and humongous object allocation
tonyp
parents:
1552
diff
changeset
|
584 G1BlockOffsetArray::set_for_starts_humongous(HeapWord* new_end) { |
72a161e62cc4
6991377: G1: race between concurrent refinement and humongous object allocation
tonyp
parents:
1552
diff
changeset
|
585 assert(_end == new_end, "_end should have already been updated"); |
72a161e62cc4
6991377: G1: race between concurrent refinement and humongous object allocation
tonyp
parents:
1552
diff
changeset
|
586 |
72a161e62cc4
6991377: G1: race between concurrent refinement and humongous object allocation
tonyp
parents:
1552
diff
changeset
|
587 // The first BOT entry should have offset 0. |
72a161e62cc4
6991377: G1: race between concurrent refinement and humongous object allocation
tonyp
parents:
1552
diff
changeset
|
588 _array->set_offset_array(_array->index_for(_bottom), 0); |
72a161e62cc4
6991377: G1: race between concurrent refinement and humongous object allocation
tonyp
parents:
1552
diff
changeset
|
589 // The rest should point to the first one. |
72a161e62cc4
6991377: G1: race between concurrent refinement and humongous object allocation
tonyp
parents:
1552
diff
changeset
|
590 set_remainder_to_point_to_start(_bottom + N_words, new_end); |
72a161e62cc4
6991377: G1: race between concurrent refinement and humongous object allocation
tonyp
parents:
1552
diff
changeset
|
591 } |
72a161e62cc4
6991377: G1: race between concurrent refinement and humongous object allocation
tonyp
parents:
1552
diff
changeset
|
592 |
342 | 593 ////////////////////////////////////////////////////////////////////// |
594 // G1BlockOffsetArrayContigSpace | |
595 ////////////////////////////////////////////////////////////////////// | |
596 | |
597 HeapWord* | |
598 G1BlockOffsetArrayContigSpace::block_start_unsafe(const void* addr) { | |
599 assert(_bottom <= addr && addr < _end, | |
600 "addr must be covered by this Array"); | |
601 HeapWord* q = block_at_or_preceding(addr, true, _next_offset_index-1); | |
602 return forward_to_block_containing_addr(q, addr); | |
603 } | |
604 | |
605 HeapWord* | |
606 G1BlockOffsetArrayContigSpace:: | |
607 block_start_unsafe_const(const void* addr) const { | |
608 assert(_bottom <= addr && addr < _end, | |
609 "addr must be covered by this Array"); | |
610 HeapWord* q = block_at_or_preceding(addr, true, _next_offset_index-1); | |
611 HeapWord* n = q + _sp->block_size(q); | |
612 return forward_to_block_containing_addr_const(q, n, addr); | |
613 } | |
614 | |
615 G1BlockOffsetArrayContigSpace:: | |
616 G1BlockOffsetArrayContigSpace(G1BlockOffsetSharedArray* array, | |
617 MemRegion mr) : | |
618 G1BlockOffsetArray(array, mr, true) | |
619 { | |
620 _next_offset_threshold = NULL; | |
621 _next_offset_index = 0; | |
622 } | |
623 | |
624 HeapWord* G1BlockOffsetArrayContigSpace::initialize_threshold() { | |
625 assert(!Universe::heap()->is_in_reserved(_array->_offset_array), | |
626 "just checking"); | |
627 _next_offset_index = _array->index_for(_bottom); | |
628 _next_offset_index++; | |
629 _next_offset_threshold = | |
630 _array->address_for_index(_next_offset_index); | |
631 return _next_offset_threshold; | |
632 } | |
633 | |
634 void G1BlockOffsetArrayContigSpace::zero_bottom_entry() { | |
635 assert(!Universe::heap()->is_in_reserved(_array->_offset_array), | |
636 "just checking"); | |
637 size_t bottom_index = _array->index_for(_bottom); | |
638 assert(_array->address_for_index(bottom_index) == _bottom, | |
639 "Precondition of call"); | |
640 _array->set_offset_array(bottom_index, 0); | |
641 } | |
1886
72a161e62cc4
6991377: G1: race between concurrent refinement and humongous object allocation
tonyp
parents:
1552
diff
changeset
|
642 |
72a161e62cc4
6991377: G1: race between concurrent refinement and humongous object allocation
tonyp
parents:
1552
diff
changeset
|
643 void |
72a161e62cc4
6991377: G1: race between concurrent refinement and humongous object allocation
tonyp
parents:
1552
diff
changeset
|
644 G1BlockOffsetArrayContigSpace::set_for_starts_humongous(HeapWord* new_end) { |
72a161e62cc4
6991377: G1: race between concurrent refinement and humongous object allocation
tonyp
parents:
1552
diff
changeset
|
645 G1BlockOffsetArray::set_for_starts_humongous(new_end); |
72a161e62cc4
6991377: G1: race between concurrent refinement and humongous object allocation
tonyp
parents:
1552
diff
changeset
|
646 |
72a161e62cc4
6991377: G1: race between concurrent refinement and humongous object allocation
tonyp
parents:
1552
diff
changeset
|
647 // Make sure _next_offset_threshold and _next_offset_index point to new_end. |
72a161e62cc4
6991377: G1: race between concurrent refinement and humongous object allocation
tonyp
parents:
1552
diff
changeset
|
648 _next_offset_threshold = new_end; |
72a161e62cc4
6991377: G1: race between concurrent refinement and humongous object allocation
tonyp
parents:
1552
diff
changeset
|
649 _next_offset_index = _array->index_for(new_end); |
72a161e62cc4
6991377: G1: race between concurrent refinement and humongous object allocation
tonyp
parents:
1552
diff
changeset
|
650 } |