Mercurial > hg > graal-jvmci-8
comparison src/share/vm/gc_implementation/g1/g1BlockOffsetTable.cpp @ 2133:2250ee17e258
7007068: G1: refine the BOT during evac failure handling
Summary: During evacuation failure handling we refine the BOT to reflect the location of all the objects in the regions we scan. The changeset includes some minor cleanup: a) non-product print_on() method on the G1 BOT class, b) added more complete BOT verification during heap / region verification, c) slight modification to the BOT set up for humongous regions to be more consistent with the BOT set up during evac failure handling, and d) removed a couple of unused methods.
Reviewed-by: johnc, ysr
author | tonyp |
---|---|
date | Wed, 12 Jan 2011 13:06:00 -0500 |
parents | f95d63e2154a |
children | d2a62e0f25eb |
comparison
equal
deleted
inserted
replaced
2132:4947ee68d19c | 2133:2250ee17e258 |
---|---|
1 /* | 1 /* |
2 * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. | 2 * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * | 4 * |
5 * This code is free software; you can redistribute it and/or modify it | 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 | 6 * under the terms of the GNU General Public License version 2 only, as |
7 * published by the Free Software Foundation. | 7 * published by the Free Software Foundation. |
220 } | 220 } |
221 | 221 |
222 | 222 |
223 // Action_mark - update the BOT for the block [blk_start, blk_end). | 223 // Action_mark - update the BOT for the block [blk_start, blk_end). |
224 // Current typical use is for splitting a block. | 224 // Current typical use is for splitting a block. |
225 // Action_single - udpate the BOT for an allocation. | 225 // Action_single - update the BOT for an allocation. |
226 // Action_verify - BOT verification. | 226 // Action_verify - BOT verification. |
227 void G1BlockOffsetArray::do_block_internal(HeapWord* blk_start, | 227 void G1BlockOffsetArray::do_block_internal(HeapWord* blk_start, |
228 HeapWord* blk_end, | 228 HeapWord* blk_end, |
229 Action action) { | 229 Action action) { |
230 assert(Universe::heap()->is_in_reserved(blk_start), | 230 assert(Universe::heap()->is_in_reserved(blk_start), |
329 void | 329 void |
330 G1BlockOffsetArray::mark_block(HeapWord* blk_start, HeapWord* blk_end) { | 330 G1BlockOffsetArray::mark_block(HeapWord* blk_start, HeapWord* blk_end) { |
331 do_block_internal(blk_start, blk_end, Action_mark); | 331 do_block_internal(blk_start, blk_end, Action_mark); |
332 } | 332 } |
333 | 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) { | 334 HeapWord* G1BlockOffsetArray::block_start_unsafe(const void* addr) { |
376 assert(_bottom <= addr && addr < _end, | 335 assert(_bottom <= addr && addr < _end, |
377 "addr must be covered by this Array"); | 336 "addr must be covered by this Array"); |
378 // Must read this exactly once because it can be modified by parallel | 337 // Must read this exactly once because it can be modified by parallel |
379 // allocation. | 338 // allocation. |
578 "offset array should have been set"); | 537 "offset array should have been set"); |
579 } | 538 } |
580 #endif | 539 #endif |
581 } | 540 } |
582 | 541 |
583 void | 542 bool |
584 G1BlockOffsetArray::set_for_starts_humongous(HeapWord* new_end) { | 543 G1BlockOffsetArray::verify_for_object(HeapWord* obj_start, |
585 assert(_end == new_end, "_end should have already been updated"); | 544 size_t word_size) const { |
586 | 545 size_t first_card = _array->index_for(obj_start); |
587 // The first BOT entry should have offset 0. | 546 size_t last_card = _array->index_for(obj_start + word_size - 1); |
588 _array->set_offset_array(_array->index_for(_bottom), 0); | 547 if (!_array->is_card_boundary(obj_start)) { |
589 // The rest should point to the first one. | 548 // If the object is not on a card boundary the BOT entry of the |
590 set_remainder_to_point_to_start(_bottom + N_words, new_end); | 549 // first card should point to another object so we should not |
591 } | 550 // check that one. |
551 first_card += 1; | |
552 } | |
553 for (size_t card = first_card; card <= last_card; card += 1) { | |
554 HeapWord* card_addr = _array->address_for_index(card); | |
555 HeapWord* block_start = block_start_const(card_addr); | |
556 if (block_start != obj_start) { | |
557 gclog_or_tty->print_cr("block start: "PTR_FORMAT" is incorrect - " | |
558 "card index: "SIZE_FORMAT" " | |
559 "card addr: "PTR_FORMAT" BOT entry: %u " | |
560 "obj: "PTR_FORMAT" word size: "SIZE_FORMAT" " | |
561 "cards: ["SIZE_FORMAT","SIZE_FORMAT"]", | |
562 block_start, card, card_addr, | |
563 _array->offset_array(card), | |
564 obj_start, word_size, first_card, last_card); | |
565 return false; | |
566 } | |
567 } | |
568 return true; | |
569 } | |
570 | |
571 #ifndef PRODUCT | |
572 void | |
573 G1BlockOffsetArray::print_on(outputStream* out) { | |
574 size_t from_index = _array->index_for(_bottom); | |
575 size_t to_index = _array->index_for(_end); | |
576 out->print_cr(">> BOT for area ["PTR_FORMAT","PTR_FORMAT") " | |
577 "cards ["SIZE_FORMAT","SIZE_FORMAT")", | |
578 _bottom, _end, from_index, to_index); | |
579 for (size_t i = from_index; i < to_index; ++i) { | |
580 out->print_cr(" entry "SIZE_FORMAT_W(8)" | "PTR_FORMAT" : %3u", | |
581 i, _array->address_for_index(i), | |
582 (uint) _array->offset_array(i)); | |
583 } | |
584 } | |
585 #endif // !PRODUCT | |
592 | 586 |
593 ////////////////////////////////////////////////////////////////////// | 587 ////////////////////////////////////////////////////////////////////// |
594 // G1BlockOffsetArrayContigSpace | 588 // G1BlockOffsetArrayContigSpace |
595 ////////////////////////////////////////////////////////////////////// | 589 ////////////////////////////////////////////////////////////////////// |
596 | 590 |
639 "Precondition of call"); | 633 "Precondition of call"); |
640 _array->set_offset_array(bottom_index, 0); | 634 _array->set_offset_array(bottom_index, 0); |
641 } | 635 } |
642 | 636 |
643 void | 637 void |
644 G1BlockOffsetArrayContigSpace::set_for_starts_humongous(HeapWord* new_end) { | 638 G1BlockOffsetArrayContigSpace::set_for_starts_humongous(HeapWord* new_top) { |
645 G1BlockOffsetArray::set_for_starts_humongous(new_end); | 639 assert(new_top <= _end, "_end should have already been updated"); |
646 | 640 |
647 // Make sure _next_offset_threshold and _next_offset_index point to new_end. | 641 // The first BOT entry should have offset 0. |
648 _next_offset_threshold = new_end; | 642 zero_bottom_entry(); |
649 _next_offset_index = _array->index_for(new_end); | 643 initialize_threshold(); |
650 } | 644 alloc_block(_bottom, new_top); |
645 } | |
646 | |
647 #ifndef PRODUCT | |
648 void | |
649 G1BlockOffsetArrayContigSpace::print_on(outputStream* out) { | |
650 G1BlockOffsetArray::print_on(out); | |
651 out->print_cr(" next offset threshold: "PTR_FORMAT, _next_offset_threshold); | |
652 out->print_cr(" next offset index: "SIZE_FORMAT, _next_offset_index); | |
653 } | |
654 #endif // !PRODUCT |