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