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