mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 14:54:52 +02:00
8038423: G1: Decommit memory within heap
Allow G1 to decommit memory of arbitrary regions within the heap and their associated auxiliary data structures card table, BOT, hot card cache, and mark bitmaps. Reviewed-by: mgerdin, brutisso, jwilhelm
This commit is contained in:
parent
2617d54723
commit
100e51a339
32 changed files with 1322 additions and 579 deletions
|
@ -32,64 +32,37 @@
|
|||
|
||||
PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
|
||||
|
||||
void G1BlockOffsetSharedArrayMappingChangedListener::on_commit(uint start_idx, size_t num_regions) {
|
||||
// Nothing to do. The BOT is hard-wired to be part of the HeapRegion, and we cannot
|
||||
// retrieve it here since this would cause firing of several asserts. The code
|
||||
// executed after commit of a region already needs to do some re-initialization of
|
||||
// the HeapRegion, so we combine that.
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// G1BlockOffsetSharedArray
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
G1BlockOffsetSharedArray::G1BlockOffsetSharedArray(MemRegion reserved,
|
||||
size_t init_word_size) :
|
||||
_reserved(reserved), _end(NULL)
|
||||
{
|
||||
size_t size = compute_size(reserved.word_size());
|
||||
ReservedSpace rs(ReservedSpace::allocation_align_size_up(size));
|
||||
if (!rs.is_reserved()) {
|
||||
vm_exit_during_initialization("Could not reserve enough space for heap offset array");
|
||||
}
|
||||
if (!_vs.initialize(rs, 0)) {
|
||||
vm_exit_during_initialization("Could not reserve enough space for heap offset array");
|
||||
}
|
||||
G1BlockOffsetSharedArray::G1BlockOffsetSharedArray(MemRegion heap, G1RegionToSpaceMapper* storage) :
|
||||
_reserved(), _end(NULL), _listener(), _offset_array(NULL) {
|
||||
|
||||
MemTracker::record_virtual_memory_type((address)rs.base(), mtGC);
|
||||
_reserved = heap;
|
||||
_end = NULL;
|
||||
|
||||
MemRegion bot_reserved = storage->reserved();
|
||||
|
||||
_offset_array = (u_char*)bot_reserved.start();
|
||||
_end = _reserved.end();
|
||||
|
||||
storage->set_mapping_changed_listener(&_listener);
|
||||
|
||||
_offset_array = (u_char*)_vs.low_boundary();
|
||||
resize(init_word_size);
|
||||
if (TraceBlockOffsetTable) {
|
||||
gclog_or_tty->print_cr("G1BlockOffsetSharedArray::G1BlockOffsetSharedArray: ");
|
||||
gclog_or_tty->print_cr(" "
|
||||
" rs.base(): " INTPTR_FORMAT
|
||||
" rs.size(): " INTPTR_FORMAT
|
||||
" rs end(): " INTPTR_FORMAT,
|
||||
rs.base(), rs.size(), rs.base() + rs.size());
|
||||
gclog_or_tty->print_cr(" "
|
||||
" _vs.low_boundary(): " INTPTR_FORMAT
|
||||
" _vs.high_boundary(): " INTPTR_FORMAT,
|
||||
_vs.low_boundary(),
|
||||
_vs.high_boundary());
|
||||
}
|
||||
}
|
||||
|
||||
void G1BlockOffsetSharedArray::resize(size_t new_word_size) {
|
||||
assert(new_word_size <= _reserved.word_size(), "Resize larger than reserved");
|
||||
size_t new_size = compute_size(new_word_size);
|
||||
size_t old_size = _vs.committed_size();
|
||||
size_t delta;
|
||||
char* high = _vs.high();
|
||||
_end = _reserved.start() + new_word_size;
|
||||
if (new_size > old_size) {
|
||||
delta = ReservedSpace::page_align_size_up(new_size - old_size);
|
||||
assert(delta > 0, "just checking");
|
||||
if (!_vs.expand_by(delta)) {
|
||||
// Do better than this for Merlin
|
||||
vm_exit_out_of_memory(delta, OOM_MMAP_ERROR, "offset table expansion");
|
||||
}
|
||||
assert(_vs.high() == high + delta, "invalid expansion");
|
||||
// Initialization of the contents is left to the
|
||||
// G1BlockOffsetArray that uses it.
|
||||
} else {
|
||||
delta = ReservedSpace::page_align_size_down(old_size - new_size);
|
||||
if (delta == 0) return;
|
||||
_vs.shrink_by(delta);
|
||||
assert(_vs.high() == high - delta, "invalid expansion");
|
||||
bot_reserved.start(), bot_reserved.byte_size(), bot_reserved.end());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -100,18 +73,7 @@ bool G1BlockOffsetSharedArray::is_card_boundary(HeapWord* p) const {
|
|||
}
|
||||
|
||||
void G1BlockOffsetSharedArray::set_offset_array(HeapWord* left, HeapWord* right, u_char offset) {
|
||||
check_index(index_for(right - 1), "right address out of range");
|
||||
assert(left < right, "Heap addresses out of order");
|
||||
size_t num_cards = pointer_delta(right, left) >> LogN_words;
|
||||
if (UseMemSetInBOT) {
|
||||
memset(&_offset_array[index_for(left)], offset, num_cards);
|
||||
} else {
|
||||
size_t i = index_for(left);
|
||||
const size_t end = i + num_cards;
|
||||
for (; i < end; i++) {
|
||||
_offset_array[i] = offset;
|
||||
}
|
||||
}
|
||||
set_offset_array(index_for(left), index_for(right -1), offset);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
@ -650,6 +612,25 @@ G1BlockOffsetArrayContigSpace(G1BlockOffsetSharedArray* array,
|
|||
_next_offset_index = 0;
|
||||
}
|
||||
|
||||
HeapWord* G1BlockOffsetArrayContigSpace::initialize_threshold_raw() {
|
||||
assert(!Universe::heap()->is_in_reserved(_array->_offset_array),
|
||||
"just checking");
|
||||
_next_offset_index = _array->index_for_raw(_bottom);
|
||||
_next_offset_index++;
|
||||
_next_offset_threshold =
|
||||
_array->address_for_index_raw(_next_offset_index);
|
||||
return _next_offset_threshold;
|
||||
}
|
||||
|
||||
void G1BlockOffsetArrayContigSpace::zero_bottom_entry_raw() {
|
||||
assert(!Universe::heap()->is_in_reserved(_array->_offset_array),
|
||||
"just checking");
|
||||
size_t bottom_index = _array->index_for_raw(_bottom);
|
||||
assert(_array->address_for_index_raw(bottom_index) == _bottom,
|
||||
"Precondition of call");
|
||||
_array->set_offset_array_raw(bottom_index, 0);
|
||||
}
|
||||
|
||||
HeapWord* G1BlockOffsetArrayContigSpace::initialize_threshold() {
|
||||
assert(!Universe::heap()->is_in_reserved(_array->_offset_array),
|
||||
"just checking");
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue