< prev index next >
src/share/vm/gc_implementation/shenandoah/shenandoahHeapRegion.cpp
Print this page
rev 10654 : [backport] Disable ShHeapUncommit on too-large large-pages
rev 10658 : [backport] Single marking bitmap
rev 10660 : [backport] Refactor bitmap cleaning
rev 10673 : [backport] Homogenize unimplemented stubs handling
rev 10676 : [backport] Remove ShHeap::region_in_collection_set in favor of SHR::in_cset
rev 10690 : [backport] Cleanup header files and forward declarations
rev 10712 : [backport] Fix compilation errors due to missing spaces between string literal and macro
rev 10740 : [backport] Protect more internal code from false sharing
rev 10747 : [backport] Fix Windows build failure
rev 10764 : [backport] Rename BrooksPointer to ShenandoahBrooksPointer
rev 10766 : Cast Shenandoah{Min,Max}RegionSize to size_t
rev 10772 : [backport] Update copyrights
*** 1,7 ****
/*
! * Copyright (c) 2013, 2015, Red Hat, Inc. and/or its affiliates.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
--- 1,7 ----
/*
! * Copyright (c) 2013, 2018, Red Hat, Inc. All rights reserved.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
*** 20,36 ****
* questions.
*
*/
#include "precompiled.hpp"
#include "memory/allocation.hpp"
! #include "gc_implementation/shenandoah/brooksPointer.hpp"
#include "gc_implementation/shenandoah/shenandoahHeap.hpp"
#include "gc_implementation/shenandoah/shenandoahHeap.inline.hpp"
#include "gc_implementation/shenandoah/shenandoahHeapRegion.hpp"
#include "gc_implementation/shenandoah/shenandoahMarkingContext.inline.hpp"
#include "memory/space.inline.hpp"
#include "memory/universe.hpp"
#include "oops/oop.inline.hpp"
#include "runtime/java.hpp"
#include "runtime/mutexLocker.hpp"
#include "runtime/os.hpp"
--- 20,38 ----
* questions.
*
*/
#include "precompiled.hpp"
+
#include "memory/allocation.hpp"
! #include "gc_implementation/shenandoah/shenandoahBrooksPointer.hpp"
#include "gc_implementation/shenandoah/shenandoahHeap.hpp"
#include "gc_implementation/shenandoah/shenandoahHeap.inline.hpp"
#include "gc_implementation/shenandoah/shenandoahHeapRegion.hpp"
#include "gc_implementation/shenandoah/shenandoahMarkingContext.inline.hpp"
#include "memory/space.inline.hpp"
+ #include "memory/resourceArea.hpp"
#include "memory/universe.hpp"
#include "oops/oop.inline.hpp"
#include "runtime/java.hpp"
#include "runtime/mutexLocker.hpp"
#include "runtime/os.hpp"
*** 49,69 ****
size_t ShenandoahHeapRegion::MaxTLABSizeWords = 0;
ShenandoahHeapRegion::ShenandoahHeapRegion(ShenandoahHeap* heap, HeapWord* start,
size_t size_words, size_t index, bool committed) :
_heap(heap),
! _region_number(index),
! _live_data(0),
_reserved(MemRegion(start, size_words)),
! _tlab_allocs(0),
! _gclab_allocs(0),
! _shared_allocs(0),
_new_top(NULL),
_critical_pins(0),
- _state(committed ? _empty_committed : _empty_uncommitted),
_empty_time(os::elapsedTime()),
! _pacer(ShenandoahPacing ? heap->pacer() : NULL) {
ContiguousSpace::initialize(_reserved, true, committed);
}
size_t ShenandoahHeapRegion::region_number() const {
--- 51,71 ----
size_t ShenandoahHeapRegion::MaxTLABSizeWords = 0;
ShenandoahHeapRegion::ShenandoahHeapRegion(ShenandoahHeap* heap, HeapWord* start,
size_t size_words, size_t index, bool committed) :
_heap(heap),
! _pacer(ShenandoahPacing ? heap->pacer() : NULL),
_reserved(MemRegion(start, size_words)),
! _region_number(index),
_new_top(NULL),
_critical_pins(0),
_empty_time(os::elapsedTime()),
! _state(committed ? _empty_committed : _empty_uncommitted),
! _tlab_allocs(0),
! _gclab_allocs(0),
! _shared_allocs(0),
! _live_data(0) {
ContiguousSpace::initialize(_reserved, true, committed);
}
size_t ShenandoahHeapRegion::region_number() const {
*** 263,272 ****
--- 265,282 ----
default:
report_illegal_transition("trashing");
}
}
+ void ShenandoahHeapRegion::make_trash_immediate() {
+ make_trash();
+
+ // On this path, we know there are no marked objects in the region,
+ // tell marking context about it to bypass bitmap resets.
+ _heap->complete_marking_context()->reset_top_bitmap(this);
+ }
+
void ShenandoahHeapRegion::make_empty() {
_heap->assert_heaplock_owned_by_current_thread();
switch (_state) {
case _trash:
_state = _empty_committed;
*** 301,315 ****
default:
report_illegal_transition("commit bypass");
}
}
- bool ShenandoahHeapRegion::rollback_allocation(uint size) {
- set_top(top() - size);
- return true;
- }
-
void ShenandoahHeapRegion::clear_live_data() {
OrderAccess::release_store_fence((volatile jint*)&_live_data, 0);
}
void ShenandoahHeapRegion::reset_alloc_metadata() {
--- 311,320 ----
*** 360,379 ****
bool ShenandoahHeapRegion::has_live() const {
return get_live_data_words() != 0;
}
size_t ShenandoahHeapRegion::garbage() const {
! assert(used() >= get_live_data_bytes(), err_msg("Live Data must be a subset of used() live: "SIZE_FORMAT" used: "SIZE_FORMAT,
get_live_data_bytes(), used()));
size_t result = used() - get_live_data_bytes();
return result;
}
- bool ShenandoahHeapRegion::in_collection_set() const {
- return _heap->region_in_collection_set(_region_number);
- }
-
void ShenandoahHeapRegion::print_on(outputStream* st) const {
st->print("|");
st->print(SIZE_FORMAT_W(5), this->_region_number);
switch (_state) {
--- 365,380 ----
bool ShenandoahHeapRegion::has_live() const {
return get_live_data_words() != 0;
}
size_t ShenandoahHeapRegion::garbage() const {
! assert(used() >= get_live_data_bytes(), err_msg("Live Data must be a subset of used() live: " SIZE_FORMAT " used: " SIZE_FORMAT,
get_live_data_bytes(), used()));
size_t result = used() - get_live_data_bytes();
return result;
}
void ShenandoahHeapRegion::print_on(outputStream* st) const {
st->print("|");
st->print(SIZE_FORMAT_W(5), this->_region_number);
switch (_state) {
*** 410,441 ****
default:
ShouldNotReachHere();
}
st->print("|BTE " INTPTR_FORMAT_W(12) ", " INTPTR_FORMAT_W(12) ", " INTPTR_FORMAT_W(12),
p2i(bottom()), p2i(top()), p2i(end()));
! st->print("|TAMS " INTPTR_FORMAT_W(12) ", " INTPTR_FORMAT_W(12),
! p2i(_heap->complete_marking_context()->top_at_mark_start(region_number())),
! p2i(_heap->next_marking_context()->top_at_mark_start(region_number())));
st->print("|U " SIZE_FORMAT_W(5) "%1s", byte_size_in_proper_unit(used()), proper_unit_for_byte_size(used()));
st->print("|T " SIZE_FORMAT_W(5) "%1s", byte_size_in_proper_unit(get_tlab_allocs()), proper_unit_for_byte_size(get_tlab_allocs()));
st->print("|G " SIZE_FORMAT_W(5) "%1s", byte_size_in_proper_unit(get_gclab_allocs()), proper_unit_for_byte_size(get_gclab_allocs()));
st->print("|S " SIZE_FORMAT_W(5) "%1s", byte_size_in_proper_unit(get_shared_allocs()), proper_unit_for_byte_size(get_shared_allocs()));
st->print("|L " SIZE_FORMAT_W(5) "%1s", byte_size_in_proper_unit(get_live_data_bytes()), proper_unit_for_byte_size(get_live_data_bytes()));
st->print("|CP " SIZE_FORMAT_W(3), _critical_pins);
st->cr();
}
- void ShenandoahHeapRegion::fill_region() {
- if (free() > (BrooksPointer::word_size() + CollectedHeap::min_fill_size())) {
- HeapWord* filler = allocate(BrooksPointer::word_size(), ShenandoahHeap::_alloc_shared);
- HeapWord* obj = allocate(end() - top(), ShenandoahHeap::_alloc_shared);
- _heap->fill_with_object(obj, end() - obj);
- BrooksPointer::initialize(oop(obj));
- }
- }
-
ShenandoahHeapRegion* ShenandoahHeapRegion::humongous_start_region() const {
assert(is_humongous(), "Must be a part of the humongous region");
size_t reg_num = region_number();
ShenandoahHeapRegion* r = const_cast<ShenandoahHeapRegion*>(this);
while (!r->is_humongous_start()) {
--- 411,432 ----
default:
ShouldNotReachHere();
}
st->print("|BTE " INTPTR_FORMAT_W(12) ", " INTPTR_FORMAT_W(12) ", " INTPTR_FORMAT_W(12),
p2i(bottom()), p2i(top()), p2i(end()));
! st->print("|TAMS " INTPTR_FORMAT_W(12),
! p2i(_heap->marking_context()->top_at_mark_start(const_cast<ShenandoahHeapRegion*>(this))));
st->print("|U " SIZE_FORMAT_W(5) "%1s", byte_size_in_proper_unit(used()), proper_unit_for_byte_size(used()));
st->print("|T " SIZE_FORMAT_W(5) "%1s", byte_size_in_proper_unit(get_tlab_allocs()), proper_unit_for_byte_size(get_tlab_allocs()));
st->print("|G " SIZE_FORMAT_W(5) "%1s", byte_size_in_proper_unit(get_gclab_allocs()), proper_unit_for_byte_size(get_gclab_allocs()));
st->print("|S " SIZE_FORMAT_W(5) "%1s", byte_size_in_proper_unit(get_shared_allocs()), proper_unit_for_byte_size(get_shared_allocs()));
st->print("|L " SIZE_FORMAT_W(5) "%1s", byte_size_in_proper_unit(get_live_data_bytes()), proper_unit_for_byte_size(get_live_data_bytes()));
st->print("|CP " SIZE_FORMAT_W(3), _critical_pins);
st->cr();
}
ShenandoahHeapRegion* ShenandoahHeapRegion::humongous_start_region() const {
assert(is_humongous(), "Must be a part of the humongous region");
size_t reg_num = region_number();
ShenandoahHeapRegion* r = const_cast<ShenandoahHeapRegion*>(this);
while (!r->is_humongous_start()) {
*** 454,496 ****
ContiguousSpace::mangle_unused_area_complete();
}
clear_live_data();
reset_alloc_metadata();
! ShenandoahMarkingContext* const compl_ctx = _heap->complete_marking_context();
!
! // Reset C-TAMS pointer to ensure size-based iteration, everything
! // in that regions is going to be new objects.
! compl_ctx->set_top_at_mark_start(region_number(), bottom());
! // We can only safely reset the C-TAMS pointer if the bitmap is clear for that region.
! assert(compl_ctx->is_bitmap_clear_range(bottom(), end()), "must be clear");
make_empty();
}
HeapWord* ShenandoahHeapRegion::block_start_const(const void* p) const {
assert(MemRegion(bottom(), end()).contains(p),
! err_msg("p ("PTR_FORMAT") not in space ["PTR_FORMAT", "PTR_FORMAT")",
p2i(p), p2i(bottom()), p2i(end())));
if (p >= top()) {
return top();
} else {
! HeapWord* last = bottom() + BrooksPointer::word_size();
HeapWord* cur = last;
while (cur <= p) {
last = cur;
! cur += oop(cur)->size() + BrooksPointer::word_size();
}
shenandoah_assert_correct(NULL, oop(last));
return last;
}
}
void ShenandoahHeapRegion::setup_sizes(size_t initial_heap_size, size_t max_heap_size) {
// Absolute minimums we should not ever break:
static const size_t MIN_REGION_SIZE = 256*K;
- static const size_t MIN_NUM_REGIONS = 10;
size_t region_size;
if (FLAG_IS_DEFAULT(ShenandoahHeapRegionSize)) {
if (ShenandoahMinRegionSize > initial_heap_size / MIN_NUM_REGIONS) {
err_msg message("Initial heap size (" SIZE_FORMAT "K) is too low to afford the minimum number "
--- 445,480 ----
ContiguousSpace::mangle_unused_area_complete();
}
clear_live_data();
reset_alloc_metadata();
! _heap->marking_context()->reset_top_at_mark_start(this);
make_empty();
}
HeapWord* ShenandoahHeapRegion::block_start_const(const void* p) const {
assert(MemRegion(bottom(), end()).contains(p),
! err_msg("p (" PTR_FORMAT ") not in space [" PTR_FORMAT ", " PTR_FORMAT ")",
p2i(p), p2i(bottom()), p2i(end())));
if (p >= top()) {
return top();
} else {
! HeapWord* last = bottom() + ShenandoahBrooksPointer::word_size();
HeapWord* cur = last;
while (cur <= p) {
last = cur;
! cur += oop(cur)->size() + ShenandoahBrooksPointer::word_size();
}
shenandoah_assert_correct(NULL, oop(last));
return last;
}
}
void ShenandoahHeapRegion::setup_sizes(size_t initial_heap_size, size_t max_heap_size) {
// Absolute minimums we should not ever break:
static const size_t MIN_REGION_SIZE = 256*K;
size_t region_size;
if (FLAG_IS_DEFAULT(ShenandoahHeapRegionSize)) {
if (ShenandoahMinRegionSize > initial_heap_size / MIN_NUM_REGIONS) {
err_msg message("Initial heap size (" SIZE_FORMAT "K) is too low to afford the minimum number "
*** 522,533 ****
// We rapidly expand to max_heap_size in most scenarios, so that is the measure
// for usual heap sizes. Do not depend on initial_heap_size here.
region_size = max_heap_size / ShenandoahTargetNumRegions;
// Now make sure that we don't go over or under our limits.
! region_size = MAX2(ShenandoahMinRegionSize, region_size);
! region_size = MIN2(ShenandoahMaxRegionSize, region_size);
} else {
if (ShenandoahHeapRegionSize > initial_heap_size / MIN_NUM_REGIONS) {
err_msg message("Initial heap size (" SIZE_FORMAT "K) is too low to afford the minimum number "
"of regions (" SIZE_FORMAT ") of requested size (" SIZE_FORMAT "K).",
--- 506,517 ----
// We rapidly expand to max_heap_size in most scenarios, so that is the measure
// for usual heap sizes. Do not depend on initial_heap_size here.
region_size = max_heap_size / ShenandoahTargetNumRegions;
// Now make sure that we don't go over or under our limits.
! region_size = MAX2<size_t>(ShenandoahMinRegionSize, region_size);
! region_size = MIN2<size_t>(ShenandoahMaxRegionSize, region_size);
} else {
if (ShenandoahHeapRegionSize > initial_heap_size / MIN_NUM_REGIONS) {
err_msg message("Initial heap size (" SIZE_FORMAT "K) is too low to afford the minimum number "
"of regions (" SIZE_FORMAT ") of requested size (" SIZE_FORMAT "K).",
*** 550,570 ****
if (1 > ShenandoahHumongousThreshold || ShenandoahHumongousThreshold > 100) {
vm_exit_during_initialization("Invalid -XX:ShenandoahHumongousThreshold option, should be within [1..100]");
}
// Make sure region size is at least one large page, if enabled.
! // Otherwise, mem-protecting one region may falsely protect the adjacent
// regions too.
! if (UseLargePages) {
region_size = MAX2(region_size, os::large_page_size());
}
int region_size_log = log2_long((jlong) region_size);
// Recalculate the region size to make sure it's a power of
// 2. This means that region_size is the largest power of 2 that's
// <= what we've calculated so far.
! region_size = (size_t(1) << region_size_log);
// Now, set up the globals.
guarantee(RegionSizeBytesShift == 0, "we should only set it once");
RegionSizeBytesShift = (size_t)region_size_log;
--- 534,555 ----
if (1 > ShenandoahHumongousThreshold || ShenandoahHumongousThreshold > 100) {
vm_exit_during_initialization("Invalid -XX:ShenandoahHumongousThreshold option, should be within [1..100]");
}
// Make sure region size is at least one large page, if enabled.
! // Otherwise, uncommitting one region may falsely uncommit the adjacent
// regions too.
! // Also see shenandoahArguments.cpp, where it handles UseLargePages.
! if (UseLargePages && ShenandoahUncommit) {
region_size = MAX2(region_size, os::large_page_size());
}
int region_size_log = log2_long((jlong) region_size);
// Recalculate the region size to make sure it's a power of
// 2. This means that region_size is the largest power of 2 that's
// <= what we've calculated so far.
! region_size = size_t(1) << region_size_log;
// Now, set up the globals.
guarantee(RegionSizeBytesShift == 0, "we should only set it once");
RegionSizeBytesShift = (size_t)region_size_log;
< prev index next >