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 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
24
25 #include "precompiled.hpp"
26 #include "gc_implementation/g1/g1BlockOffsetTable.inline.hpp"
27 #include "gc_implementation/g1/heapRegion.hpp"
28 #include "memory/space.hpp"
29 #include "oops/oop.inline.hpp"
30 #include "runtime/java.hpp"
31 #include "services/memTracker.hpp"
32
33 PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
34
35 void G1BlockOffsetSharedArrayMappingChangedListener::on_commit(uint start_idx, size_t num_regions) {
36 // Nothing to do. The BOT is hard-wired to be part of the HeapRegion, and we cannot
37 // retrieve it here since this would cause firing of several asserts. The code
38 // executed after commit of a region already needs to do some re-initialization of
39 // the HeapRegion, so we combine that.
40 }
41
42 //////////////////////////////////////////////////////////////////////
43 // G1BlockOffsetSharedArray
44 //////////////////////////////////////////////////////////////////////
45
46 G1BlockOffsetSharedArray::G1BlockOffsetSharedArray(MemRegion heap, G1RegionToSpaceMapper* storage) :
47 _reserved(), _end(NULL), _listener(), _offset_array(NULL) {
48
49 _reserved = heap;
50 _end = NULL;
51
52 MemRegion bot_reserved = storage->reserved();
53
54 _offset_array = (u_char*)bot_reserved.start();
55 _end = _reserved.end();
56
57 storage->set_mapping_changed_listener(&_listener);
58
59 if (TraceBlockOffsetTable) {
60 gclog_or_tty->print_cr("G1BlockOffsetSharedArray::G1BlockOffsetSharedArray: ");
61 gclog_or_tty->print_cr(" "
62 " rs.base(): " INTPTR_FORMAT
63 " rs.size(): " INTPTR_FORMAT
64 " rs end(): " INTPTR_FORMAT,
65 bot_reserved.start(), bot_reserved.byte_size(), bot_reserved.end());
66 }
67 }
68
69 bool G1BlockOffsetSharedArray::is_card_boundary(HeapWord* p) const {
70 assert(p >= _reserved.start(), "just checking");
71 size_t delta = pointer_delta(p, _reserved.start());
72 return (delta & right_n_bits(LogN_words)) == (size_t)NoBits;
73 }
74
75 void G1BlockOffsetSharedArray::set_offset_array(HeapWord* left, HeapWord* right, u_char offset) {
76 set_offset_array(index_for(left), index_for(right -1), offset);
77 }
78
79 //////////////////////////////////////////////////////////////////////
80 // G1BlockOffsetArray
81 //////////////////////////////////////////////////////////////////////
82
83 G1BlockOffsetArray::G1BlockOffsetArray(G1BlockOffsetSharedArray* array,
84 MemRegion mr, bool init_to_zero) :
85 G1BlockOffsetTable(mr.start(), mr.end()),
364 HeapWord* n,
365 const void* addr) {
366 // We're not in the normal case. We need to handle an important subcase
367 // here: LAB allocation. An allocation previously recorded in the
368 // offset table was actually a lab allocation, and was divided into
369 // several objects subsequently. Fix this situation as we answer the
370 // query, by updating entries as we cross them.
371
372 // If the fist object's end q is at the card boundary. Start refining
373 // with the corresponding card (the value of the entry will be basically
374 // set to 0). If the object crosses the boundary -- start from the next card.
375 size_t n_index = _array->index_for(n);
376 size_t next_index = _array->index_for(n) + !_array->is_card_boundary(n);
377 // Calculate a consistent next boundary. If "n" is not at the boundary
378 // already, step to the boundary.
379 HeapWord* next_boundary = _array->address_for_index(n_index) +
380 (n_index == next_index ? 0 : N_words);
381 assert(next_boundary <= _array->_end,
382 err_msg("next_boundary is beyond the end of the covered region "
383 " next_boundary " PTR_FORMAT " _array->_end " PTR_FORMAT,
384 next_boundary, _array->_end));
385 if (addr >= gsp()->top()) return gsp()->top();
386 while (next_boundary < addr) {
387 while (n <= next_boundary) {
388 q = n;
389 oop obj = oop(q);
390 if (obj->klass_or_null() == NULL) return q;
391 n += block_size(q);
392 }
393 assert(q <= next_boundary && n > next_boundary, "Consequence of loop");
394 // [q, n) is the block that crosses the boundary.
395 alloc_block_work2(&next_boundary, &next_index, q, n);
396 }
397 return forward_to_block_containing_addr_const(q, n, addr);
398 }
399
400 HeapWord* G1BlockOffsetArray::block_start_careful(const void* addr) const {
401 assert(_array->offset_array(0) == 0, "objects can't cross covered areas");
402
403 assert(_bottom <= addr && addr < _end,
404 "addr must be covered by this Array");
505 assert(threshold >= blk_end, "Incorrect offset threshold");
506
507 // index_ and threshold_ updated here.
508 *threshold_ = threshold;
509 *index_ = index;
510
511 #ifdef ASSERT
512 // The offset can be 0 if the block starts on a boundary. That
513 // is checked by an assertion above.
514 size_t start_index = _array->index_for(blk_start);
515 HeapWord* boundary = _array->address_for_index(start_index);
516 assert((_array->offset_array(orig_index) == 0 &&
517 blk_start == boundary) ||
518 (_array->offset_array(orig_index) > 0 &&
519 _array->offset_array(orig_index) <= N_words),
520 err_msg("offset array should have been set - "
521 "orig_index offset: %u, "
522 "blk_start: " PTR_FORMAT ", "
523 "boundary: " PTR_FORMAT,
524 (uint)_array->offset_array(orig_index),
525 blk_start, boundary));
526 for (size_t j = orig_index + 1; j <= end_index; j++) {
527 assert(_array->offset_array(j) > 0 &&
528 _array->offset_array(j) <=
529 (u_char) (N_words+BlockOffsetArray::N_powers-1),
530 err_msg("offset array should have been set - "
531 "%u not > 0 OR %u not <= %u",
532 (uint) _array->offset_array(j),
533 (uint) _array->offset_array(j),
534 (uint) (N_words+BlockOffsetArray::N_powers-1)));
535 }
536 #endif
537 }
538
539 bool
540 G1BlockOffsetArray::verify_for_object(HeapWord* obj_start,
541 size_t word_size) const {
542 size_t first_card = _array->index_for(obj_start);
543 size_t last_card = _array->index_for(obj_start + word_size - 1);
544 if (!_array->is_card_boundary(obj_start)) {
545 // If the object is not on a card boundary the BOT entry of the
546 // first card should point to another object so we should not
547 // check that one.
548 first_card += 1;
549 }
550 for (size_t card = first_card; card <= last_card; card += 1) {
551 HeapWord* card_addr = _array->address_for_index(card);
552 HeapWord* block_start = block_start_const(card_addr);
553 if (block_start != obj_start) {
554 gclog_or_tty->print_cr("block start: "PTR_FORMAT" is incorrect - "
555 "card index: "SIZE_FORMAT" "
556 "card addr: "PTR_FORMAT" BOT entry: %u "
557 "obj: "PTR_FORMAT" word size: "SIZE_FORMAT" "
558 "cards: ["SIZE_FORMAT","SIZE_FORMAT"]",
559 block_start, card, card_addr,
560 _array->offset_array(card),
561 obj_start, word_size, first_card, last_card);
562 return false;
563 }
564 }
565 return true;
566 }
567
568 #ifndef PRODUCT
569 void
570 G1BlockOffsetArray::print_on(outputStream* out) {
571 size_t from_index = _array->index_for(_bottom);
572 size_t to_index = _array->index_for(_end);
573 out->print_cr(">> BOT for area ["PTR_FORMAT","PTR_FORMAT") "
574 "cards ["SIZE_FORMAT","SIZE_FORMAT")",
575 _bottom, _end, from_index, to_index);
576 for (size_t i = from_index; i < to_index; ++i) {
577 out->print_cr(" entry "SIZE_FORMAT_W(8)" | "PTR_FORMAT" : %3u",
578 i, _array->address_for_index(i),
579 (uint) _array->offset_array(i));
580 }
581 }
582 #endif // !PRODUCT
583
584 //////////////////////////////////////////////////////////////////////
585 // G1BlockOffsetArrayContigSpace
586 //////////////////////////////////////////////////////////////////////
587
588 HeapWord*
589 G1BlockOffsetArrayContigSpace::block_start_unsafe(const void* addr) {
590 assert(_bottom <= addr && addr < _end,
591 "addr must be covered by this Array");
592 HeapWord* q = block_at_or_preceding(addr, true, _next_offset_index-1);
593 return forward_to_block_containing_addr(q, addr);
594 }
595
596 HeapWord*
597 G1BlockOffsetArrayContigSpace::
598 block_start_unsafe_const(const void* addr) const {
646 "just checking");
647 size_t bottom_index = _array->index_for(_bottom);
648 assert(_array->address_for_index(bottom_index) == _bottom,
649 "Precondition of call");
650 _array->set_offset_array(bottom_index, 0);
651 }
652
653 void
654 G1BlockOffsetArrayContigSpace::set_for_starts_humongous(HeapWord* new_top) {
655 assert(new_top <= _end, "_end should have already been updated");
656
657 // The first BOT entry should have offset 0.
658 reset_bot();
659 alloc_block(_bottom, new_top);
660 }
661
662 #ifndef PRODUCT
663 void
664 G1BlockOffsetArrayContigSpace::print_on(outputStream* out) {
665 G1BlockOffsetArray::print_on(out);
666 out->print_cr(" next offset threshold: "PTR_FORMAT, _next_offset_threshold);
667 out->print_cr(" next offset index: "SIZE_FORMAT, _next_offset_index);
668 }
669 #endif // !PRODUCT
|
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 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
24
25 #include "precompiled.hpp"
26 #include "gc_implementation/g1/g1BlockOffsetTable.inline.hpp"
27 #include "gc_implementation/g1/heapRegion.hpp"
28 #include "memory/space.hpp"
29 #include "oops/oop.inline.hpp"
30 #include "runtime/java.hpp"
31 #include "services/memTracker.hpp"
32
33
34
35 void G1BlockOffsetSharedArrayMappingChangedListener::on_commit(uint start_idx, size_t num_regions) {
36 // Nothing to do. The BOT is hard-wired to be part of the HeapRegion, and we cannot
37 // retrieve it here since this would cause firing of several asserts. The code
38 // executed after commit of a region already needs to do some re-initialization of
39 // the HeapRegion, so we combine that.
40 }
41
42 //////////////////////////////////////////////////////////////////////
43 // G1BlockOffsetSharedArray
44 //////////////////////////////////////////////////////////////////////
45
46 G1BlockOffsetSharedArray::G1BlockOffsetSharedArray(MemRegion heap, G1RegionToSpaceMapper* storage) :
47 _reserved(), _end(NULL), _listener(), _offset_array(NULL) {
48
49 _reserved = heap;
50 _end = NULL;
51
52 MemRegion bot_reserved = storage->reserved();
53
54 _offset_array = (u_char*)bot_reserved.start();
55 _end = _reserved.end();
56
57 storage->set_mapping_changed_listener(&_listener);
58
59 if (TraceBlockOffsetTable) {
60 gclog_or_tty->print_cr("G1BlockOffsetSharedArray::G1BlockOffsetSharedArray: ");
61 gclog_or_tty->print_cr(" "
62 " rs.base(): " PTR_FORMAT
63 " rs.size(): " SIZE_FORMAT
64 " rs end(): " PTR_FORMAT,
65 p2i(bot_reserved.start()), bot_reserved.byte_size(), p2i(bot_reserved.end()));
66 }
67 }
68
69 bool G1BlockOffsetSharedArray::is_card_boundary(HeapWord* p) const {
70 assert(p >= _reserved.start(), "just checking");
71 size_t delta = pointer_delta(p, _reserved.start());
72 return (delta & right_n_bits(LogN_words)) == (size_t)NoBits;
73 }
74
75 void G1BlockOffsetSharedArray::set_offset_array(HeapWord* left, HeapWord* right, u_char offset) {
76 set_offset_array(index_for(left), index_for(right -1), offset);
77 }
78
79 //////////////////////////////////////////////////////////////////////
80 // G1BlockOffsetArray
81 //////////////////////////////////////////////////////////////////////
82
83 G1BlockOffsetArray::G1BlockOffsetArray(G1BlockOffsetSharedArray* array,
84 MemRegion mr, bool init_to_zero) :
85 G1BlockOffsetTable(mr.start(), mr.end()),
364 HeapWord* n,
365 const void* addr) {
366 // We're not in the normal case. We need to handle an important subcase
367 // here: LAB allocation. An allocation previously recorded in the
368 // offset table was actually a lab allocation, and was divided into
369 // several objects subsequently. Fix this situation as we answer the
370 // query, by updating entries as we cross them.
371
372 // If the fist object's end q is at the card boundary. Start refining
373 // with the corresponding card (the value of the entry will be basically
374 // set to 0). If the object crosses the boundary -- start from the next card.
375 size_t n_index = _array->index_for(n);
376 size_t next_index = _array->index_for(n) + !_array->is_card_boundary(n);
377 // Calculate a consistent next boundary. If "n" is not at the boundary
378 // already, step to the boundary.
379 HeapWord* next_boundary = _array->address_for_index(n_index) +
380 (n_index == next_index ? 0 : N_words);
381 assert(next_boundary <= _array->_end,
382 err_msg("next_boundary is beyond the end of the covered region "
383 " next_boundary " PTR_FORMAT " _array->_end " PTR_FORMAT,
384 p2i(next_boundary), p2i(_array->_end)));
385 if (addr >= gsp()->top()) return gsp()->top();
386 while (next_boundary < addr) {
387 while (n <= next_boundary) {
388 q = n;
389 oop obj = oop(q);
390 if (obj->klass_or_null() == NULL) return q;
391 n += block_size(q);
392 }
393 assert(q <= next_boundary && n > next_boundary, "Consequence of loop");
394 // [q, n) is the block that crosses the boundary.
395 alloc_block_work2(&next_boundary, &next_index, q, n);
396 }
397 return forward_to_block_containing_addr_const(q, n, addr);
398 }
399
400 HeapWord* G1BlockOffsetArray::block_start_careful(const void* addr) const {
401 assert(_array->offset_array(0) == 0, "objects can't cross covered areas");
402
403 assert(_bottom <= addr && addr < _end,
404 "addr must be covered by this Array");
505 assert(threshold >= blk_end, "Incorrect offset threshold");
506
507 // index_ and threshold_ updated here.
508 *threshold_ = threshold;
509 *index_ = index;
510
511 #ifdef ASSERT
512 // The offset can be 0 if the block starts on a boundary. That
513 // is checked by an assertion above.
514 size_t start_index = _array->index_for(blk_start);
515 HeapWord* boundary = _array->address_for_index(start_index);
516 assert((_array->offset_array(orig_index) == 0 &&
517 blk_start == boundary) ||
518 (_array->offset_array(orig_index) > 0 &&
519 _array->offset_array(orig_index) <= N_words),
520 err_msg("offset array should have been set - "
521 "orig_index offset: %u, "
522 "blk_start: " PTR_FORMAT ", "
523 "boundary: " PTR_FORMAT,
524 (uint)_array->offset_array(orig_index),
525 p2i(blk_start), p2i(boundary)));
526 for (size_t j = orig_index + 1; j <= end_index; j++) {
527 assert(_array->offset_array(j) > 0 &&
528 _array->offset_array(j) <=
529 (u_char) (N_words+BlockOffsetArray::N_powers-1),
530 err_msg("offset array should have been set - "
531 "%u not > 0 OR %u not <= %u",
532 (uint) _array->offset_array(j),
533 (uint) _array->offset_array(j),
534 (uint) (N_words+BlockOffsetArray::N_powers-1)));
535 }
536 #endif
537 }
538
539 bool
540 G1BlockOffsetArray::verify_for_object(HeapWord* obj_start,
541 size_t word_size) const {
542 size_t first_card = _array->index_for(obj_start);
543 size_t last_card = _array->index_for(obj_start + word_size - 1);
544 if (!_array->is_card_boundary(obj_start)) {
545 // If the object is not on a card boundary the BOT entry of the
546 // first card should point to another object so we should not
547 // check that one.
548 first_card += 1;
549 }
550 for (size_t card = first_card; card <= last_card; card += 1) {
551 HeapWord* card_addr = _array->address_for_index(card);
552 HeapWord* block_start = block_start_const(card_addr);
553 if (block_start != obj_start) {
554 gclog_or_tty->print_cr("block start: "PTR_FORMAT" is incorrect - "
555 "card index: "SIZE_FORMAT" "
556 "card addr: "PTR_FORMAT" BOT entry: %u "
557 "obj: "PTR_FORMAT" word size: "SIZE_FORMAT" "
558 "cards: ["SIZE_FORMAT","SIZE_FORMAT"]",
559 p2i(block_start), card, p2i(card_addr),
560 _array->offset_array(card),
561 p2i(obj_start), word_size, first_card, last_card);
562 return false;
563 }
564 }
565 return true;
566 }
567
568 #ifndef PRODUCT
569 void
570 G1BlockOffsetArray::print_on(outputStream* out) {
571 size_t from_index = _array->index_for(_bottom);
572 size_t to_index = _array->index_for(_end);
573 out->print_cr(">> BOT for area ["PTR_FORMAT","PTR_FORMAT") "
574 "cards ["SIZE_FORMAT","SIZE_FORMAT")",
575 p2i(_bottom), p2i(_end), from_index, to_index);
576 for (size_t i = from_index; i < to_index; ++i) {
577 out->print_cr(" entry "SIZE_FORMAT_W(8)" | "PTR_FORMAT" : %3u",
578 i, p2i(_array->address_for_index(i)),
579 (uint) _array->offset_array(i));
580 }
581 }
582 #endif // !PRODUCT
583
584 //////////////////////////////////////////////////////////////////////
585 // G1BlockOffsetArrayContigSpace
586 //////////////////////////////////////////////////////////////////////
587
588 HeapWord*
589 G1BlockOffsetArrayContigSpace::block_start_unsafe(const void* addr) {
590 assert(_bottom <= addr && addr < _end,
591 "addr must be covered by this Array");
592 HeapWord* q = block_at_or_preceding(addr, true, _next_offset_index-1);
593 return forward_to_block_containing_addr(q, addr);
594 }
595
596 HeapWord*
597 G1BlockOffsetArrayContigSpace::
598 block_start_unsafe_const(const void* addr) const {
646 "just checking");
647 size_t bottom_index = _array->index_for(_bottom);
648 assert(_array->address_for_index(bottom_index) == _bottom,
649 "Precondition of call");
650 _array->set_offset_array(bottom_index, 0);
651 }
652
653 void
654 G1BlockOffsetArrayContigSpace::set_for_starts_humongous(HeapWord* new_top) {
655 assert(new_top <= _end, "_end should have already been updated");
656
657 // The first BOT entry should have offset 0.
658 reset_bot();
659 alloc_block(_bottom, new_top);
660 }
661
662 #ifndef PRODUCT
663 void
664 G1BlockOffsetArrayContigSpace::print_on(outputStream* out) {
665 G1BlockOffsetArray::print_on(out);
666 out->print_cr(" next offset threshold: "PTR_FORMAT, p2i(_next_offset_threshold));
667 out->print_cr(" next offset index: "SIZE_FORMAT, _next_offset_index);
668 }
669 #endif // !PRODUCT
|