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