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 //////////////////////////////////////////////////////////////////////
36 // G1BlockOffsetSharedArray
37 //////////////////////////////////////////////////////////////////////
38
39 G1BlockOffsetSharedArray::G1BlockOffsetSharedArray(MemRegion reserved,
40 size_t init_word_size) :
41 _reserved(reserved), _end(NULL)
42 {
43 size_t size = compute_size(reserved.word_size());
44 ReservedSpace rs(ReservedSpace::allocation_align_size_up(size));
45 if (!rs.is_reserved()) {
46 vm_exit_during_initialization("Could not reserve enough space for heap offset array");
47 }
48 if (!_vs.initialize(rs, 0)) {
49 vm_exit_during_initialization("Could not reserve enough space for heap offset array");
50 }
51
52 MemTracker::record_virtual_memory_type((address)rs.base(), mtGC);
53
54 _offset_array = (u_char*)_vs.low_boundary();
55 resize(init_word_size);
56 if (TraceBlockOffsetTable) {
57 gclog_or_tty->print_cr("G1BlockOffsetSharedArray::G1BlockOffsetSharedArray: ");
58 gclog_or_tty->print_cr(" "
59 " rs.base(): " INTPTR_FORMAT
60 " rs.size(): " INTPTR_FORMAT
61 " rs end(): " INTPTR_FORMAT,
62 rs.base(), rs.size(), rs.base() + rs.size());
63 gclog_or_tty->print_cr(" "
64 " _vs.low_boundary(): " INTPTR_FORMAT
65 " _vs.high_boundary(): " INTPTR_FORMAT,
66 _vs.low_boundary(),
67 _vs.high_boundary());
68 }
69 }
70
71 void G1BlockOffsetSharedArray::resize(size_t new_word_size) {
72 assert(new_word_size <= _reserved.word_size(), "Resize larger than reserved");
73 size_t new_size = compute_size(new_word_size);
74 size_t old_size = _vs.committed_size();
75 size_t delta;
76 char* high = _vs.high();
77 _end = _reserved.start() + new_word_size;
78 if (new_size > old_size) {
79 delta = ReservedSpace::page_align_size_up(new_size - old_size);
80 assert(delta > 0, "just checking");
81 if (!_vs.expand_by(delta)) {
82 // Do better than this for Merlin
83 vm_exit_out_of_memory(delta, OOM_MMAP_ERROR, "offset table expansion");
84 }
85 assert(_vs.high() == high + delta, "invalid expansion");
86 // Initialization of the contents is left to the
87 // G1BlockOffsetArray that uses it.
88 } else {
89 delta = ReservedSpace::page_align_size_down(old_size - new_size);
90 if (delta == 0) return;
91 _vs.shrink_by(delta);
92 assert(_vs.high() == high - delta, "invalid expansion");
93 }
94 }
95
96 bool G1BlockOffsetSharedArray::is_card_boundary(HeapWord* p) const {
97 assert(p >= _reserved.start(), "just checking");
98 size_t delta = pointer_delta(p, _reserved.start());
99 return (delta & right_n_bits(LogN_words)) == (size_t)NoBits;
100 }
101
102 void G1BlockOffsetSharedArray::set_offset_array(HeapWord* left, HeapWord* right, u_char offset) {
103 check_index(index_for(right - 1), "right address out of range");
104 assert(left < right, "Heap addresses out of order");
105 size_t num_cards = pointer_delta(right, left) >> LogN_words;
106 if (UseMemSetInBOT) {
107 memset(&_offset_array[index_for(left)], offset, num_cards);
108 } else {
109 size_t i = index_for(left);
110 const size_t end = i + num_cards;
111 for (; i < end; i++) {
112 _offset_array[i] = offset;
113 }
114 }
115 }
116
117 //////////////////////////////////////////////////////////////////////
118 // G1BlockOffsetArray
119 //////////////////////////////////////////////////////////////////////
120
121 G1BlockOffsetArray::G1BlockOffsetArray(G1BlockOffsetSharedArray* array,
122 MemRegion mr, bool init_to_zero) :
123 G1BlockOffsetTable(mr.start(), mr.end()),
124 _unallocated_block(_bottom),
125 _array(array), _gsp(NULL),
126 _init_to_zero(init_to_zero) {
127 assert(_bottom <= _end, "arguments out of order");
128 if (!_init_to_zero) {
129 // initialize cards to point back to mr.start()
130 set_remainder_to_point_to_start(mr.start() + N_words, mr.end());
131 _array->set_offset_array(0, 0); // set first card to 0
132 }
133 }
134
631 return forward_to_block_containing_addr(q, addr);
632 }
633
634 HeapWord*
635 G1BlockOffsetArrayContigSpace::
636 block_start_unsafe_const(const void* addr) const {
637 assert(_bottom <= addr && addr < _end,
638 "addr must be covered by this Array");
639 HeapWord* q = block_at_or_preceding(addr, true, _next_offset_index-1);
640 HeapWord* n = q + block_size(q);
641 return forward_to_block_containing_addr_const(q, n, addr);
642 }
643
644 G1BlockOffsetArrayContigSpace::
645 G1BlockOffsetArrayContigSpace(G1BlockOffsetSharedArray* array,
646 MemRegion mr) :
647 G1BlockOffsetArray(array, mr, true)
648 {
649 _next_offset_threshold = NULL;
650 _next_offset_index = 0;
651 }
652
653 HeapWord* G1BlockOffsetArrayContigSpace::initialize_threshold() {
654 assert(!Universe::heap()->is_in_reserved(_array->_offset_array),
655 "just checking");
656 _next_offset_index = _array->index_for(_bottom);
657 _next_offset_index++;
658 _next_offset_threshold =
659 _array->address_for_index(_next_offset_index);
660 return _next_offset_threshold;
661 }
662
663 void G1BlockOffsetArrayContigSpace::zero_bottom_entry() {
664 assert(!Universe::heap()->is_in_reserved(_array->_offset_array),
665 "just checking");
666 size_t bottom_index = _array->index_for(_bottom);
667 assert(_array->address_for_index(bottom_index) == _bottom,
668 "Precondition of call");
669 _array->set_offset_array(bottom_index, 0);
670 }
|
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()),
86 _unallocated_block(_bottom),
87 _array(array), _gsp(NULL),
88 _init_to_zero(init_to_zero) {
89 assert(_bottom <= _end, "arguments out of order");
90 if (!_init_to_zero) {
91 // initialize cards to point back to mr.start()
92 set_remainder_to_point_to_start(mr.start() + N_words, mr.end());
93 _array->set_offset_array(0, 0); // set first card to 0
94 }
95 }
96
593 return forward_to_block_containing_addr(q, addr);
594 }
595
596 HeapWord*
597 G1BlockOffsetArrayContigSpace::
598 block_start_unsafe_const(const void* addr) const {
599 assert(_bottom <= addr && addr < _end,
600 "addr must be covered by this Array");
601 HeapWord* q = block_at_or_preceding(addr, true, _next_offset_index-1);
602 HeapWord* n = q + block_size(q);
603 return forward_to_block_containing_addr_const(q, n, addr);
604 }
605
606 G1BlockOffsetArrayContigSpace::
607 G1BlockOffsetArrayContigSpace(G1BlockOffsetSharedArray* array,
608 MemRegion mr) :
609 G1BlockOffsetArray(array, mr, true)
610 {
611 _next_offset_threshold = NULL;
612 _next_offset_index = 0;
613 }
614
615 HeapWord* G1BlockOffsetArrayContigSpace::initialize_threshold_raw() {
616 assert(!Universe::heap()->is_in_reserved(_array->_offset_array),
617 "just checking");
618 _next_offset_index = _array->index_for_raw(_bottom);
619 _next_offset_index++;
620 _next_offset_threshold =
621 _array->address_for_index_raw(_next_offset_index);
622 return _next_offset_threshold;
623 }
624
625 void G1BlockOffsetArrayContigSpace::zero_bottom_entry_raw() {
626 assert(!Universe::heap()->is_in_reserved(_array->_offset_array),
627 "just checking");
628 size_t bottom_index = _array->index_for_raw(_bottom);
629 assert(_array->address_for_index_raw(bottom_index) == _bottom,
630 "Precondition of call");
631 _array->set_offset_array_raw(bottom_index, 0);
632 }
633
634 HeapWord* G1BlockOffsetArrayContigSpace::initialize_threshold() {
635 assert(!Universe::heap()->is_in_reserved(_array->_offset_array),
636 "just checking");
637 _next_offset_index = _array->index_for(_bottom);
638 _next_offset_index++;
639 _next_offset_threshold =
640 _array->address_for_index(_next_offset_index);
641 return _next_offset_threshold;
642 }
643
644 void G1BlockOffsetArrayContigSpace::zero_bottom_entry() {
645 assert(!Universe::heap()->is_in_reserved(_array->_offset_array),
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 }
|