8256181: Remove Allocation of old generation on alternate memory devices functionality
Reviewed-by: ayang, iignatyev, iklam
This commit is contained in:
parent
4df8abc200
commit
bd8693a084
@ -4624,7 +4624,7 @@ jint os::init_2(void) {
|
||||
// initialize thread priority policy
|
||||
prio_init();
|
||||
|
||||
if (!FLAG_IS_DEFAULT(AllocateHeapAt) || !FLAG_IS_DEFAULT(AllocateOldGenAt)) {
|
||||
if (!FLAG_IS_DEFAULT(AllocateHeapAt)) {
|
||||
set_coredump_filter(DAX_SHARED_BIT);
|
||||
}
|
||||
|
||||
|
@ -36,9 +36,6 @@
|
||||
#include "runtime/globals_extension.hpp"
|
||||
#include "runtime/java.hpp"
|
||||
|
||||
static const double MaxRamFractionForYoung = 0.8;
|
||||
size_t G1Arguments::MaxMemoryForYoung;
|
||||
|
||||
static size_t calculate_heap_alignment(size_t space_alignment) {
|
||||
size_t card_table_alignment = CardTableRS::ct_max_alignment_constraint();
|
||||
size_t page_size = UseLargePages ? os::large_page_size() : os::vm_page_size();
|
||||
@ -194,85 +191,15 @@ void G1Arguments::initialize() {
|
||||
initialize_verification_types();
|
||||
}
|
||||
|
||||
static size_t calculate_reasonable_max_memory_for_young(FormatBuffer<100> &calc_str, double max_ram_fraction_for_young) {
|
||||
julong phys_mem;
|
||||
// If MaxRam is specified, we use that as maximum physical memory available.
|
||||
if (FLAG_IS_DEFAULT(MaxRAM)) {
|
||||
phys_mem = os::physical_memory();
|
||||
calc_str.append("Physical_Memory");
|
||||
} else {
|
||||
phys_mem = (julong)MaxRAM;
|
||||
calc_str.append("MaxRAM");
|
||||
}
|
||||
|
||||
julong reasonable_max = phys_mem;
|
||||
|
||||
// If either MaxRAMFraction or MaxRAMPercentage is specified, we use them to calculate
|
||||
// reasonable max size of young generation.
|
||||
if (!FLAG_IS_DEFAULT(MaxRAMFraction)) {
|
||||
reasonable_max = (julong)(phys_mem / MaxRAMFraction);
|
||||
calc_str.append(" / MaxRAMFraction");
|
||||
} else if (!FLAG_IS_DEFAULT(MaxRAMPercentage)) {
|
||||
reasonable_max = (julong)((phys_mem * MaxRAMPercentage) / 100);
|
||||
calc_str.append(" * MaxRAMPercentage / 100");
|
||||
} else {
|
||||
// We use our own fraction to calculate max size of young generation.
|
||||
reasonable_max = phys_mem * max_ram_fraction_for_young;
|
||||
calc_str.append(" * %0.2f", max_ram_fraction_for_young);
|
||||
}
|
||||
|
||||
return (size_t)reasonable_max;
|
||||
}
|
||||
|
||||
void G1Arguments::initialize_heap_flags_and_sizes() {
|
||||
if (AllocateOldGenAt != NULL) {
|
||||
initialize_heterogeneous();
|
||||
}
|
||||
|
||||
GCArguments::initialize_heap_flags_and_sizes();
|
||||
}
|
||||
|
||||
void G1Arguments::initialize_heterogeneous() {
|
||||
FormatBuffer<100> calc_str("");
|
||||
|
||||
MaxMemoryForYoung = calculate_reasonable_max_memory_for_young(calc_str, MaxRamFractionForYoung);
|
||||
|
||||
if (MaxNewSize > MaxMemoryForYoung) {
|
||||
if (FLAG_IS_CMDLINE(MaxNewSize)) {
|
||||
log_warning(gc, ergo)("Setting MaxNewSize to " SIZE_FORMAT " based on dram available (calculation = align(%s))",
|
||||
MaxMemoryForYoung, calc_str.buffer());
|
||||
} else {
|
||||
log_info(gc, ergo)("Setting MaxNewSize to " SIZE_FORMAT " based on dram available (calculation = align(%s)). "
|
||||
"Dram usage can be lowered by setting MaxNewSize to a lower value", MaxMemoryForYoung, calc_str.buffer());
|
||||
}
|
||||
MaxNewSize = MaxMemoryForYoung;
|
||||
}
|
||||
if (NewSize > MaxMemoryForYoung) {
|
||||
if (FLAG_IS_CMDLINE(NewSize)) {
|
||||
log_warning(gc, ergo)("Setting NewSize to " SIZE_FORMAT " based on dram available (calculation = align(%s))",
|
||||
MaxMemoryForYoung, calc_str.buffer());
|
||||
}
|
||||
NewSize = MaxMemoryForYoung;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
CollectedHeap* G1Arguments::create_heap() {
|
||||
return new G1CollectedHeap();
|
||||
}
|
||||
|
||||
bool G1Arguments::is_heterogeneous_heap() {
|
||||
return AllocateOldGenAt != NULL;
|
||||
}
|
||||
|
||||
size_t G1Arguments::reasonable_max_memory_for_young() {
|
||||
return MaxMemoryForYoung;
|
||||
}
|
||||
|
||||
size_t G1Arguments::heap_reserved_size_bytes() {
|
||||
return (is_heterogeneous_heap() ? 2 : 1) * MaxHeapSize;
|
||||
}
|
||||
|
||||
size_t G1Arguments::heap_max_size_bytes() {
|
||||
return MaxHeapSize;
|
||||
}
|
||||
|
||||
|
@ -33,9 +33,6 @@ class CollectedHeap;
|
||||
class G1Arguments : public GCArguments {
|
||||
friend class G1HeapVerifierTest;
|
||||
|
||||
private:
|
||||
static size_t MaxMemoryForYoung;
|
||||
|
||||
static void initialize_mark_stack_size();
|
||||
static void initialize_verification_types();
|
||||
static void parse_verification_type(const char* type);
|
||||
@ -43,18 +40,12 @@ private:
|
||||
virtual void initialize_alignments();
|
||||
virtual void initialize_heap_flags_and_sizes();
|
||||
|
||||
void initialize_heterogeneous();
|
||||
|
||||
virtual void initialize();
|
||||
virtual size_t conservative_max_heap_alignment();
|
||||
virtual CollectedHeap* create_heap();
|
||||
|
||||
public:
|
||||
// Heterogeneous heap support
|
||||
static bool is_heterogeneous_heap();
|
||||
static size_t reasonable_max_memory_for_young();
|
||||
static size_t heap_reserved_size_bytes();
|
||||
static size_t heap_max_size_bytes();
|
||||
};
|
||||
|
||||
#endif // SHARE_GC_G1_G1ARGUMENTS_HPP
|
||||
|
@ -184,7 +184,7 @@ HeapRegion* G1CollectedHeap::new_region(size_t word_size,
|
||||
"the only time we use this to allocate a humongous region is "
|
||||
"when we are allocating a single humongous region");
|
||||
|
||||
HeapRegion* res = _hrm->allocate_free_region(type, node_index);
|
||||
HeapRegion* res = _hrm.allocate_free_region(type, node_index);
|
||||
|
||||
if (res == NULL && do_expand && _expand_heap_after_alloc_failure) {
|
||||
// Currently, only attempts to allocate GC alloc regions set
|
||||
@ -204,7 +204,7 @@ HeapRegion* G1CollectedHeap::new_region(size_t word_size,
|
||||
// always expand the heap by an amount aligned to the heap
|
||||
// region size, the free list should in theory not be empty.
|
||||
// In either case allocate_free_region() will check for NULL.
|
||||
res = _hrm->allocate_free_region(type, node_index);
|
||||
res = _hrm.allocate_free_region(type, node_index);
|
||||
} else {
|
||||
_expand_heap_after_alloc_failure = false;
|
||||
}
|
||||
@ -346,12 +346,12 @@ HeapWord* G1CollectedHeap::humongous_obj_allocate(size_t word_size) {
|
||||
uint obj_regions = (uint) humongous_obj_size_in_regions(word_size);
|
||||
|
||||
// Policy: First try to allocate a humongous object in the free list.
|
||||
HeapRegion* humongous_start = _hrm->allocate_humongous(obj_regions);
|
||||
HeapRegion* humongous_start = _hrm.allocate_humongous(obj_regions);
|
||||
if (humongous_start == NULL) {
|
||||
// Policy: We could not find enough regions for the humongous object in the
|
||||
// free list. Look through the heap to find a mix of free and uncommitted regions.
|
||||
// If so, expand the heap and allocate the humongous object.
|
||||
humongous_start = _hrm->expand_and_allocate_humongous(obj_regions);
|
||||
humongous_start = _hrm.expand_and_allocate_humongous(obj_regions);
|
||||
if (humongous_start != NULL) {
|
||||
// We managed to find a region by expanding the heap.
|
||||
log_debug(gc, ergo, heap)("Heap expansion (humongous allocation request). Allocation request: " SIZE_FORMAT "B",
|
||||
@ -545,7 +545,7 @@ void G1CollectedHeap::end_archive_alloc_range(GrowableArray<MemRegion>* ranges,
|
||||
bool G1CollectedHeap::check_archive_addresses(MemRegion* ranges, size_t count) {
|
||||
assert(ranges != NULL, "MemRegion array NULL");
|
||||
assert(count != 0, "No MemRegions provided");
|
||||
MemRegion reserved = _hrm->reserved();
|
||||
MemRegion reserved = _hrm.reserved();
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
if (!reserved.contains(ranges[i].start()) || !reserved.contains(ranges[i].last())) {
|
||||
return false;
|
||||
@ -562,7 +562,7 @@ bool G1CollectedHeap::alloc_archive_regions(MemRegion* ranges,
|
||||
assert(count != 0, "No MemRegions provided");
|
||||
MutexLocker x(Heap_lock);
|
||||
|
||||
MemRegion reserved = _hrm->reserved();
|
||||
MemRegion reserved = _hrm.reserved();
|
||||
HeapWord* prev_last_addr = NULL;
|
||||
HeapRegion* prev_last_region = NULL;
|
||||
|
||||
@ -592,7 +592,7 @@ bool G1CollectedHeap::alloc_archive_regions(MemRegion* ranges,
|
||||
// range ended, and adjust the start address so we don't try to allocate
|
||||
// the same region again. If the current range is entirely within that
|
||||
// region, skip it, just adjusting the recorded top.
|
||||
HeapRegion* start_region = _hrm->addr_to_region(start_address);
|
||||
HeapRegion* start_region = _hrm.addr_to_region(start_address);
|
||||
if ((prev_last_region != NULL) && (start_region == prev_last_region)) {
|
||||
start_address = start_region->end();
|
||||
if (start_address > last_address) {
|
||||
@ -602,12 +602,12 @@ bool G1CollectedHeap::alloc_archive_regions(MemRegion* ranges,
|
||||
}
|
||||
start_region->set_top(start_address);
|
||||
curr_range = MemRegion(start_address, last_address + 1);
|
||||
start_region = _hrm->addr_to_region(start_address);
|
||||
start_region = _hrm.addr_to_region(start_address);
|
||||
}
|
||||
|
||||
// Perform the actual region allocation, exiting if it fails.
|
||||
// Then note how much new space we have allocated.
|
||||
if (!_hrm->allocate_containing_regions(curr_range, &commits, workers())) {
|
||||
if (!_hrm.allocate_containing_regions(curr_range, &commits, workers())) {
|
||||
return false;
|
||||
}
|
||||
increase_used(word_size * HeapWordSize);
|
||||
@ -619,8 +619,8 @@ bool G1CollectedHeap::alloc_archive_regions(MemRegion* ranges,
|
||||
|
||||
// Mark each G1 region touched by the range as archive, add it to
|
||||
// the old set, and set top.
|
||||
HeapRegion* curr_region = _hrm->addr_to_region(start_address);
|
||||
HeapRegion* last_region = _hrm->addr_to_region(last_address);
|
||||
HeapRegion* curr_region = _hrm.addr_to_region(start_address);
|
||||
HeapRegion* last_region = _hrm.addr_to_region(last_address);
|
||||
prev_last_region = last_region;
|
||||
|
||||
while (curr_region != NULL) {
|
||||
@ -637,7 +637,7 @@ bool G1CollectedHeap::alloc_archive_regions(MemRegion* ranges,
|
||||
HeapRegion* next_region;
|
||||
if (curr_region != last_region) {
|
||||
top = curr_region->end();
|
||||
next_region = _hrm->next_region_in_heap(curr_region);
|
||||
next_region = _hrm.next_region_in_heap(curr_region);
|
||||
} else {
|
||||
top = last_address + 1;
|
||||
next_region = NULL;
|
||||
@ -653,7 +653,7 @@ void G1CollectedHeap::fill_archive_regions(MemRegion* ranges, size_t count) {
|
||||
assert(!is_init_completed(), "Expect to be called at JVM init time");
|
||||
assert(ranges != NULL, "MemRegion array NULL");
|
||||
assert(count != 0, "No MemRegions provided");
|
||||
MemRegion reserved = _hrm->reserved();
|
||||
MemRegion reserved = _hrm.reserved();
|
||||
HeapWord *prev_last_addr = NULL;
|
||||
HeapRegion* prev_last_region = NULL;
|
||||
|
||||
@ -673,8 +673,8 @@ void G1CollectedHeap::fill_archive_regions(MemRegion* ranges, size_t count) {
|
||||
"Ranges not in ascending order: " PTR_FORMAT " <= " PTR_FORMAT ,
|
||||
p2i(start_address), p2i(prev_last_addr));
|
||||
|
||||
HeapRegion* start_region = _hrm->addr_to_region(start_address);
|
||||
HeapRegion* last_region = _hrm->addr_to_region(last_address);
|
||||
HeapRegion* start_region = _hrm.addr_to_region(start_address);
|
||||
HeapRegion* last_region = _hrm.addr_to_region(last_address);
|
||||
HeapWord* bottom_address = start_region->bottom();
|
||||
|
||||
// Check for a range beginning in the same region in which the
|
||||
@ -690,7 +690,7 @@ void G1CollectedHeap::fill_archive_regions(MemRegion* ranges, size_t count) {
|
||||
guarantee(curr_region->is_archive(),
|
||||
"Expected archive region at index %u", curr_region->hrm_index());
|
||||
if (curr_region != last_region) {
|
||||
curr_region = _hrm->next_region_in_heap(curr_region);
|
||||
curr_region = _hrm.next_region_in_heap(curr_region);
|
||||
} else {
|
||||
curr_region = NULL;
|
||||
}
|
||||
@ -739,7 +739,7 @@ void G1CollectedHeap::dealloc_archive_regions(MemRegion* ranges, size_t count) {
|
||||
assert(!is_init_completed(), "Expect to be called at JVM init time");
|
||||
assert(ranges != NULL, "MemRegion array NULL");
|
||||
assert(count != 0, "No MemRegions provided");
|
||||
MemRegion reserved = _hrm->reserved();
|
||||
MemRegion reserved = _hrm.reserved();
|
||||
HeapWord* prev_last_addr = NULL;
|
||||
HeapRegion* prev_last_region = NULL;
|
||||
size_t size_used = 0;
|
||||
@ -761,8 +761,8 @@ void G1CollectedHeap::dealloc_archive_regions(MemRegion* ranges, size_t count) {
|
||||
size_used += ranges[i].byte_size();
|
||||
prev_last_addr = last_address;
|
||||
|
||||
HeapRegion* start_region = _hrm->addr_to_region(start_address);
|
||||
HeapRegion* last_region = _hrm->addr_to_region(last_address);
|
||||
HeapRegion* start_region = _hrm.addr_to_region(start_address);
|
||||
HeapRegion* last_region = _hrm.addr_to_region(last_address);
|
||||
|
||||
// Check for ranges that start in the same G1 region in which the previous
|
||||
// range ended, and adjust the start address so we don't try to free
|
||||
@ -773,7 +773,7 @@ void G1CollectedHeap::dealloc_archive_regions(MemRegion* ranges, size_t count) {
|
||||
if (start_address > last_address) {
|
||||
continue;
|
||||
}
|
||||
start_region = _hrm->addr_to_region(start_address);
|
||||
start_region = _hrm.addr_to_region(start_address);
|
||||
}
|
||||
prev_last_region = last_region;
|
||||
|
||||
@ -788,11 +788,11 @@ void G1CollectedHeap::dealloc_archive_regions(MemRegion* ranges, size_t count) {
|
||||
curr_region->set_free();
|
||||
curr_region->set_top(curr_region->bottom());
|
||||
if (curr_region != last_region) {
|
||||
curr_region = _hrm->next_region_in_heap(curr_region);
|
||||
curr_region = _hrm.next_region_in_heap(curr_region);
|
||||
} else {
|
||||
curr_region = NULL;
|
||||
}
|
||||
_hrm->shrink_at(curr_index, 1);
|
||||
_hrm.shrink_at(curr_index, 1);
|
||||
uncommitted_regions++;
|
||||
}
|
||||
}
|
||||
@ -1005,8 +1005,7 @@ void G1CollectedHeap::prepare_heap_for_full_collection() {
|
||||
// after this full GC.
|
||||
abandon_collection_set(collection_set());
|
||||
|
||||
hrm()->remove_all_free_regions();
|
||||
hrm()->prepare_for_full_collection_start();
|
||||
_hrm.remove_all_free_regions();
|
||||
}
|
||||
|
||||
void G1CollectedHeap::verify_before_full_collection(bool explicit_gc) {
|
||||
@ -1018,8 +1017,6 @@ void G1CollectedHeap::verify_before_full_collection(bool explicit_gc) {
|
||||
}
|
||||
|
||||
void G1CollectedHeap::prepare_heap_for_mutators() {
|
||||
hrm()->prepare_for_full_collection_end();
|
||||
|
||||
// Delete metaspaces for unloaded class loaders and clean up loader_data graph
|
||||
ClassLoaderDataGraph::purge(/*at_safepoint*/true);
|
||||
DEBUG_ONLY(MetaspaceUtils::verify();)
|
||||
@ -1058,7 +1055,7 @@ void G1CollectedHeap::abort_refinement() {
|
||||
}
|
||||
|
||||
void G1CollectedHeap::verify_after_full_collection() {
|
||||
_hrm->verify_optional();
|
||||
_hrm.verify_optional();
|
||||
_verifier->verify_region_sets_optional();
|
||||
_verifier->verify_after_gc(G1HeapVerifier::G1VerifyFull);
|
||||
|
||||
@ -1234,7 +1231,7 @@ HeapWord* G1CollectedHeap::expand_and_allocate(size_t word_size) {
|
||||
|
||||
|
||||
if (expand(expand_bytes, _workers)) {
|
||||
_hrm->verify_optional();
|
||||
_hrm.verify_optional();
|
||||
_verifier->verify_region_sets_optional();
|
||||
return attempt_allocation_at_safepoint(word_size,
|
||||
false /* expect_null_mutator_alloc_region */);
|
||||
@ -1259,7 +1256,7 @@ bool G1CollectedHeap::expand(size_t expand_bytes, WorkGang* pretouch_workers, do
|
||||
uint regions_to_expand = (uint)(aligned_expand_bytes / HeapRegion::GrainBytes);
|
||||
assert(regions_to_expand > 0, "Must expand by at least one region");
|
||||
|
||||
uint expanded_by = _hrm->expand_by(regions_to_expand, pretouch_workers);
|
||||
uint expanded_by = _hrm.expand_by(regions_to_expand, pretouch_workers);
|
||||
if (expand_time_ms != NULL) {
|
||||
*expand_time_ms = (os::elapsedTime() - expand_heap_start_time_sec) * MILLIUNITS;
|
||||
}
|
||||
@ -1274,7 +1271,7 @@ bool G1CollectedHeap::expand(size_t expand_bytes, WorkGang* pretouch_workers, do
|
||||
// The expansion of the virtual storage space was unsuccessful.
|
||||
// Let's see if it was because we ran out of swap.
|
||||
if (G1ExitOnExpansionFailure &&
|
||||
_hrm->available() >= regions_to_expand) {
|
||||
_hrm.available() >= regions_to_expand) {
|
||||
// We had head room...
|
||||
vm_exit_out_of_memory(aligned_expand_bytes, OOM_MMAP_ERROR, "G1 heap expansion");
|
||||
}
|
||||
@ -1283,10 +1280,10 @@ bool G1CollectedHeap::expand(size_t expand_bytes, WorkGang* pretouch_workers, do
|
||||
}
|
||||
|
||||
bool G1CollectedHeap::expand_single_region(uint node_index) {
|
||||
uint expanded_by = _hrm->expand_on_preferred_node(node_index);
|
||||
uint expanded_by = _hrm.expand_on_preferred_node(node_index);
|
||||
|
||||
if (expanded_by == 0) {
|
||||
assert(is_maximal_no_gc(), "Should be no regions left, available: %u", _hrm->available());
|
||||
assert(is_maximal_no_gc(), "Should be no regions left, available: %u", _hrm.available());
|
||||
log_debug(gc, ergo, heap)("Did not expand the heap (heap already fully expanded)");
|
||||
return false;
|
||||
}
|
||||
@ -1302,7 +1299,7 @@ void G1CollectedHeap::shrink_helper(size_t shrink_bytes) {
|
||||
HeapRegion::GrainBytes);
|
||||
uint num_regions_to_remove = (uint)(shrink_bytes / HeapRegion::GrainBytes);
|
||||
|
||||
uint num_regions_removed = _hrm->shrink_by(num_regions_to_remove);
|
||||
uint num_regions_removed = _hrm.shrink_by(num_regions_to_remove);
|
||||
size_t shrunk_bytes = num_regions_removed * HeapRegion::GrainBytes;
|
||||
|
||||
log_debug(gc, ergo, heap)("Shrink the heap. requested shrinking amount: " SIZE_FORMAT "B aligned shrinking amount: " SIZE_FORMAT "B attempted shrinking amount: " SIZE_FORMAT "B",
|
||||
@ -1325,11 +1322,11 @@ void G1CollectedHeap::shrink(size_t shrink_bytes) {
|
||||
// Instead of tearing down / rebuilding the free lists here, we
|
||||
// could instead use the remove_all_pending() method on free_list to
|
||||
// remove only the ones that we need to remove.
|
||||
hrm()->remove_all_free_regions();
|
||||
_hrm.remove_all_free_regions();
|
||||
shrink_helper(shrink_bytes);
|
||||
rebuild_region_sets(true /* free_list_only */);
|
||||
|
||||
_hrm->verify_optional();
|
||||
_hrm.verify_optional();
|
||||
_verifier->verify_region_sets_optional();
|
||||
}
|
||||
|
||||
@ -1408,7 +1405,7 @@ G1CollectedHeap::G1CollectedHeap() :
|
||||
_bot(NULL),
|
||||
_listener(),
|
||||
_numa(G1NUMA::create()),
|
||||
_hrm(NULL),
|
||||
_hrm(),
|
||||
_allocator(NULL),
|
||||
_verifier(NULL),
|
||||
_summary_bytes_used(0),
|
||||
@ -1428,7 +1425,7 @@ G1CollectedHeap::G1CollectedHeap() :
|
||||
_survivor(),
|
||||
_gc_timer_stw(new (ResourceObj::C_HEAP, mtGC) STWGCTimer()),
|
||||
_gc_tracer_stw(new (ResourceObj::C_HEAP, mtGC) G1NewTracer()),
|
||||
_policy(G1Policy::create_policy(_gc_timer_stw)),
|
||||
_policy(new G1Policy(_gc_timer_stw)),
|
||||
_heap_sizing_policy(NULL),
|
||||
_collection_set(this, _policy),
|
||||
_hot_card_cache(NULL),
|
||||
@ -1603,12 +1600,12 @@ jint G1CollectedHeap::initialize() {
|
||||
// Create space mappers.
|
||||
size_t page_size = actual_reserved_page_size(heap_rs);
|
||||
G1RegionToSpaceMapper* heap_storage =
|
||||
G1RegionToSpaceMapper::create_heap_mapper(heap_rs,
|
||||
heap_rs.size(),
|
||||
page_size,
|
||||
HeapRegion::GrainBytes,
|
||||
1,
|
||||
mtJavaHeap);
|
||||
G1RegionToSpaceMapper::create_mapper(heap_rs,
|
||||
heap_rs.size(),
|
||||
page_size,
|
||||
HeapRegion::GrainBytes,
|
||||
1,
|
||||
mtJavaHeap);
|
||||
if(heap_storage == NULL) {
|
||||
vm_shutdown_during_initialization("Could not initialize G1 heap");
|
||||
return JNI_ERR;
|
||||
@ -1644,9 +1641,7 @@ jint G1CollectedHeap::initialize() {
|
||||
G1RegionToSpaceMapper* next_bitmap_storage =
|
||||
create_aux_memory_mapper("Next Bitmap", bitmap_size, G1CMBitMap::heap_map_factor());
|
||||
|
||||
_hrm = HeapRegionManager::create_manager(this);
|
||||
|
||||
_hrm->initialize(heap_storage, prev_bitmap_storage, next_bitmap_storage, bot_storage, cardtable_storage, card_counts_storage);
|
||||
_hrm.initialize(heap_storage, prev_bitmap_storage, next_bitmap_storage, bot_storage, cardtable_storage, card_counts_storage);
|
||||
_card_table->initialize(cardtable_storage);
|
||||
|
||||
// Do later initialization work for concurrent refinement.
|
||||
@ -1723,7 +1718,7 @@ jint G1CollectedHeap::initialize() {
|
||||
|
||||
// Here we allocate the dummy HeapRegion that is required by the
|
||||
// G1AllocRegion class.
|
||||
HeapRegion* dummy_region = _hrm->get_dummy_region();
|
||||
HeapRegion* dummy_region = _hrm.get_dummy_region();
|
||||
|
||||
// We'll re-use the same region whether the alloc region will
|
||||
// require BOT updates or not and, if it doesn't, then a non-young
|
||||
@ -1842,11 +1837,11 @@ SoftRefPolicy* G1CollectedHeap::soft_ref_policy() {
|
||||
}
|
||||
|
||||
size_t G1CollectedHeap::capacity() const {
|
||||
return _hrm->length() * HeapRegion::GrainBytes;
|
||||
return _hrm.length() * HeapRegion::GrainBytes;
|
||||
}
|
||||
|
||||
size_t G1CollectedHeap::unused_committed_regions_in_bytes() const {
|
||||
return _hrm->total_free_bytes();
|
||||
return _hrm.total_free_bytes();
|
||||
}
|
||||
|
||||
void G1CollectedHeap::iterate_hcc_closure(G1CardTableEntryClosure* cl, uint worker_id) {
|
||||
@ -1902,9 +1897,7 @@ bool G1CollectedHeap::should_do_concurrent_full_gc(GCCause::Cause cause) {
|
||||
}
|
||||
|
||||
bool G1CollectedHeap::should_upgrade_to_full_gc(GCCause::Cause cause) {
|
||||
if (policy()->force_upgrade_to_full()) {
|
||||
return true;
|
||||
} else if (should_do_concurrent_full_gc(_gc_cause)) {
|
||||
if (should_do_concurrent_full_gc(_gc_cause)) {
|
||||
return false;
|
||||
} else if (has_regions_left_for_allocation()) {
|
||||
return false;
|
||||
@ -2238,7 +2231,7 @@ bool G1CollectedHeap::try_collect(GCCause::Cause cause) {
|
||||
}
|
||||
|
||||
bool G1CollectedHeap::is_in(const void* p) const {
|
||||
return is_in_reserved(p) && _hrm->is_available(addr_to_region((HeapWord*)p));
|
||||
return is_in_reserved(p) && _hrm.is_available(addr_to_region((HeapWord*)p));
|
||||
}
|
||||
|
||||
// Iteration functions.
|
||||
@ -2291,18 +2284,18 @@ void G1CollectedHeap::keep_alive(oop obj) {
|
||||
}
|
||||
|
||||
void G1CollectedHeap::heap_region_iterate(HeapRegionClosure* cl) const {
|
||||
_hrm->iterate(cl);
|
||||
_hrm.iterate(cl);
|
||||
}
|
||||
|
||||
void G1CollectedHeap::heap_region_par_iterate_from_worker_offset(HeapRegionClosure* cl,
|
||||
HeapRegionClaimer *hrclaimer,
|
||||
uint worker_id) const {
|
||||
_hrm->par_iterate(cl, hrclaimer, hrclaimer->offset_for_worker(worker_id));
|
||||
_hrm.par_iterate(cl, hrclaimer, hrclaimer->offset_for_worker(worker_id));
|
||||
}
|
||||
|
||||
void G1CollectedHeap::heap_region_par_iterate_from_start(HeapRegionClosure* cl,
|
||||
HeapRegionClaimer *hrclaimer) const {
|
||||
_hrm->par_iterate(cl, hrclaimer, 0);
|
||||
_hrm.par_iterate(cl, hrclaimer, 0);
|
||||
}
|
||||
|
||||
void G1CollectedHeap::collection_set_iterate_all(HeapRegionClosure* cl) {
|
||||
@ -2369,10 +2362,6 @@ bool G1CollectedHeap::supports_concurrent_gc_breakpoints() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool G1CollectedHeap::is_heterogeneous_heap() const {
|
||||
return G1Arguments::is_heterogeneous_heap();
|
||||
}
|
||||
|
||||
bool G1CollectedHeap::is_archived_object(oop object) const {
|
||||
return object != NULL && heap_region_containing(object)->is_archive();
|
||||
}
|
||||
@ -2421,13 +2410,11 @@ void G1CollectedHeap::print_heap_regions() const {
|
||||
void G1CollectedHeap::print_on(outputStream* st) const {
|
||||
size_t heap_used = Heap_lock->owned_by_self() ? used() : used_unlocked();
|
||||
st->print(" %-20s", "garbage-first heap");
|
||||
if (_hrm != NULL) {
|
||||
st->print(" total " SIZE_FORMAT "K, used " SIZE_FORMAT "K",
|
||||
capacity()/K, heap_used/K);
|
||||
st->print(" [" PTR_FORMAT ", " PTR_FORMAT ")",
|
||||
p2i(_hrm->reserved().start()),
|
||||
p2i(_hrm->reserved().end()));
|
||||
}
|
||||
st->print(" total " SIZE_FORMAT "K, used " SIZE_FORMAT "K",
|
||||
capacity()/K, heap_used/K);
|
||||
st->print(" [" PTR_FORMAT ", " PTR_FORMAT ")",
|
||||
p2i(_hrm.reserved().start()),
|
||||
p2i(_hrm.reserved().end()));
|
||||
st->cr();
|
||||
st->print(" region size " SIZE_FORMAT "K, ", HeapRegion::GrainBytes / K);
|
||||
uint young_regions = young_regions_count();
|
||||
@ -2442,7 +2429,7 @@ void G1CollectedHeap::print_on(outputStream* st) const {
|
||||
st->print(" remaining free region(s) on each NUMA node: ");
|
||||
const int* node_ids = _numa->node_ids();
|
||||
for (uint node_index = 0; node_index < num_nodes; node_index++) {
|
||||
uint num_free_regions = (_hrm != NULL ? _hrm->num_free_regions(node_index) : 0);
|
||||
uint num_free_regions = _hrm.num_free_regions(node_index);
|
||||
st->print("%d=%u ", node_ids[node_index], num_free_regions);
|
||||
}
|
||||
st->cr();
|
||||
@ -2451,10 +2438,6 @@ void G1CollectedHeap::print_on(outputStream* st) const {
|
||||
}
|
||||
|
||||
void G1CollectedHeap::print_regions_on(outputStream* st) const {
|
||||
if (_hrm == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
st->print_cr("Heap Regions: E=young(eden), S=young(survivor), O=old, "
|
||||
"HS=humongous(starts), HC=humongous(continues), "
|
||||
"CS=collection set, F=free, "
|
||||
@ -2468,10 +2451,8 @@ void G1CollectedHeap::print_extended_on(outputStream* st) const {
|
||||
print_on(st);
|
||||
|
||||
// Print the per-region information.
|
||||
if (_hrm != NULL) {
|
||||
st->cr();
|
||||
print_regions_on(st);
|
||||
}
|
||||
st->cr();
|
||||
print_regions_on(st);
|
||||
}
|
||||
|
||||
void G1CollectedHeap::print_on_error(outputStream* st) const {
|
||||
@ -3047,7 +3028,7 @@ void G1CollectedHeap::do_collection_pause_at_safepoint_helper(double target_paus
|
||||
policy()->print_phases();
|
||||
heap_transition.print();
|
||||
|
||||
_hrm->verify_optional();
|
||||
_hrm.verify_optional();
|
||||
_verifier->verify_region_sets_optional();
|
||||
|
||||
TASKQUEUE_STATS_ONLY(print_taskqueue_stats());
|
||||
@ -4009,7 +3990,7 @@ void G1CollectedHeap::record_obj_copy_mem_stats() {
|
||||
void G1CollectedHeap::free_region(HeapRegion* hr, FreeRegionList* free_list) {
|
||||
assert(!hr->is_free(), "the region should not be free");
|
||||
assert(!hr->is_empty(), "the region should not be empty");
|
||||
assert(_hrm->is_available(hr->hrm_index()), "region should be committed");
|
||||
assert(_hrm.is_available(hr->hrm_index()), "region should be committed");
|
||||
|
||||
if (G1VerifyBitmaps) {
|
||||
MemRegion mr(hr->bottom(), hr->end());
|
||||
@ -4054,7 +4035,7 @@ void G1CollectedHeap::prepend_to_freelist(FreeRegionList* list) {
|
||||
assert(list != NULL, "list can't be null");
|
||||
if (!list->is_empty()) {
|
||||
MutexLocker x(FreeList_lock, Mutex::_no_safepoint_check_flag);
|
||||
_hrm->insert_list_into_free_list(list);
|
||||
_hrm.insert_list_into_free_list(list);
|
||||
}
|
||||
}
|
||||
|
||||
@ -4335,7 +4316,7 @@ void G1CollectedHeap::free_collection_set(G1CollectionSet* collection_set, G1Eva
|
||||
phase_times()->record_total_free_cset_time_ms((free_cset_end_time - free_cset_start_time).seconds() * 1000.0);
|
||||
|
||||
// Now rebuild the free region list.
|
||||
hrm()->rebuild_free_list(workers());
|
||||
_hrm.rebuild_free_list(workers());
|
||||
phase_times()->record_total_rebuild_freelist_time_ms((Ticks::now() - free_cset_end_time).seconds() * 1000.0);
|
||||
|
||||
collection_set->clear();
|
||||
@ -4638,7 +4619,7 @@ void G1CollectedHeap::rebuild_region_sets(bool free_list_only) {
|
||||
_survivor.clear();
|
||||
}
|
||||
|
||||
RebuildRegionSetsClosure cl(free_list_only, &_old_set, _hrm);
|
||||
RebuildRegionSetsClosure cl(free_list_only, &_old_set, &_hrm);
|
||||
heap_region_iterate(&cl);
|
||||
|
||||
if (!free_list_only) {
|
||||
@ -4755,14 +4736,14 @@ void G1CollectedHeap::retire_gc_alloc_region(HeapRegion* alloc_region,
|
||||
|
||||
HeapRegion* G1CollectedHeap::alloc_highest_free_region() {
|
||||
bool expanded = false;
|
||||
uint index = _hrm->find_highest_free(&expanded);
|
||||
uint index = _hrm.find_highest_free(&expanded);
|
||||
|
||||
if (index != G1_NO_HRM_INDEX) {
|
||||
if (expanded) {
|
||||
log_debug(gc, ergo, heap)("Attempt heap expansion (requested address range outside heap bounds). region size: " SIZE_FORMAT "B",
|
||||
HeapRegion::GrainWords * HeapWordSize);
|
||||
}
|
||||
return _hrm->allocate_free_regions_starting_at(index, 1);
|
||||
return _hrm.allocate_free_regions_starting_at(index, 1);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
@ -47,7 +47,6 @@
|
||||
#include "gc/g1/g1YCTypes.hpp"
|
||||
#include "gc/g1/heapRegionManager.hpp"
|
||||
#include "gc/g1/heapRegionSet.hpp"
|
||||
#include "gc/g1/heterogeneousHeapRegionManager.hpp"
|
||||
#include "gc/shared/barrierSet.hpp"
|
||||
#include "gc/shared/collectedHeap.hpp"
|
||||
#include "gc/shared/gcHeapSummary.hpp"
|
||||
@ -194,7 +193,7 @@ private:
|
||||
G1NUMA* _numa;
|
||||
|
||||
// The sequence of all heap regions in the heap.
|
||||
HeapRegionManager* _hrm;
|
||||
HeapRegionManager _hrm;
|
||||
|
||||
// Manages all allocations with regions except humongous object allocations.
|
||||
G1Allocator* _allocator;
|
||||
@ -1016,8 +1015,6 @@ public:
|
||||
|
||||
inline G1GCPhaseTimes* phase_times() const;
|
||||
|
||||
HeapRegionManager* hrm() const { return _hrm; }
|
||||
|
||||
const G1CollectionSet* collection_set() const { return &_collection_set; }
|
||||
G1CollectionSet* collection_set() { return &_collection_set; }
|
||||
|
||||
@ -1063,7 +1060,7 @@ public:
|
||||
// But G1CollectedHeap doesn't yet support this.
|
||||
|
||||
virtual bool is_maximal_no_gc() const {
|
||||
return _hrm->available() == 0;
|
||||
return _hrm.available() == 0;
|
||||
}
|
||||
|
||||
// Returns whether there are any regions left in the heap for allocation.
|
||||
@ -1072,23 +1069,23 @@ public:
|
||||
}
|
||||
|
||||
// The current number of regions in the heap.
|
||||
uint num_regions() const { return _hrm->length(); }
|
||||
uint num_regions() const { return _hrm.length(); }
|
||||
|
||||
// The max number of regions reserved for the heap. Except for static array
|
||||
// sizing purposes you probably want to use max_regions().
|
||||
uint max_reserved_regions() const { return _hrm->reserved_length(); }
|
||||
uint max_reserved_regions() const { return _hrm.reserved_length(); }
|
||||
|
||||
// Max number of regions that can be committed.
|
||||
uint max_regions() const { return _hrm->max_length(); }
|
||||
uint max_regions() const { return _hrm.max_length(); }
|
||||
|
||||
// The number of regions that are completely free.
|
||||
uint num_free_regions() const { return _hrm->num_free_regions(); }
|
||||
uint num_free_regions() const { return _hrm.num_free_regions(); }
|
||||
|
||||
// The number of regions that can be allocated into.
|
||||
uint num_free_or_available_regions() const { return num_free_regions() + _hrm->available(); }
|
||||
uint num_free_or_available_regions() const { return num_free_regions() + _hrm.available(); }
|
||||
|
||||
MemoryUsage get_auxiliary_data_memory_usage() const {
|
||||
return _hrm->get_auxiliary_data_memory_usage();
|
||||
return _hrm.get_auxiliary_data_memory_usage();
|
||||
}
|
||||
|
||||
// The number of regions that are not completely free.
|
||||
@ -1096,7 +1093,7 @@ public:
|
||||
|
||||
#ifdef ASSERT
|
||||
bool is_on_master_free_list(HeapRegion* hr) {
|
||||
return _hrm->is_free(hr);
|
||||
return _hrm.is_free(hr);
|
||||
}
|
||||
#endif // ASSERT
|
||||
|
||||
@ -1151,7 +1148,7 @@ public:
|
||||
inline G1HeapRegionAttr region_attr(uint idx) const;
|
||||
|
||||
MemRegion reserved() const {
|
||||
return _hrm->reserved();
|
||||
return _hrm.reserved();
|
||||
}
|
||||
|
||||
bool is_in_reserved(const void* addr) const {
|
||||
@ -1414,7 +1411,6 @@ public:
|
||||
|
||||
// WhiteBox testing support.
|
||||
virtual bool supports_concurrent_gc_breakpoints() const;
|
||||
bool is_heterogeneous_heap() const;
|
||||
|
||||
virtual WorkGang* safepoint_workers() { return _workers; }
|
||||
|
||||
|
@ -64,13 +64,13 @@ size_t G1CollectedHeap::desired_plab_sz(G1HeapRegionAttr dest) {
|
||||
// Inline functions for G1CollectedHeap
|
||||
|
||||
// Return the region with the given index. It assumes the index is valid.
|
||||
inline HeapRegion* G1CollectedHeap::region_at(uint index) const { return _hrm->at(index); }
|
||||
inline HeapRegion* G1CollectedHeap::region_at(uint index) const { return _hrm.at(index); }
|
||||
|
||||
// Return the region with the given index, or NULL if unmapped. It assumes the index is valid.
|
||||
inline HeapRegion* G1CollectedHeap::region_at_or_null(uint index) const { return _hrm->at_or_null(index); }
|
||||
inline HeapRegion* G1CollectedHeap::region_at_or_null(uint index) const { return _hrm.at_or_null(index); }
|
||||
|
||||
inline HeapRegion* G1CollectedHeap::next_region_in_humongous(HeapRegion* hr) const {
|
||||
return _hrm->next_region_in_humongous(hr);
|
||||
return _hrm.next_region_in_humongous(hr);
|
||||
}
|
||||
|
||||
inline uint G1CollectedHeap::addr_to_region(HeapWord* addr) const {
|
||||
@ -81,7 +81,7 @@ inline uint G1CollectedHeap::addr_to_region(HeapWord* addr) const {
|
||||
}
|
||||
|
||||
inline HeapWord* G1CollectedHeap::bottom_addr_for_region(uint index) const {
|
||||
return _hrm->reserved().start() + index * HeapRegion::GrainWords;
|
||||
return _hrm.reserved().start() + index * HeapRegion::GrainWords;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
@ -90,7 +90,7 @@ inline HeapRegion* G1CollectedHeap::heap_region_containing(const T addr) const {
|
||||
assert(is_in_reserved((const void*) addr),
|
||||
"Address " PTR_FORMAT " is outside of the heap ranging from [" PTR_FORMAT " to " PTR_FORMAT ")",
|
||||
p2i((void*)addr), p2i(reserved().start()), p2i(reserved().end()));
|
||||
return _hrm->addr_to_region((HeapWord*)(void*) addr);
|
||||
return _hrm.addr_to_region((HeapWord*)(void*) addr);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
@ -290,12 +290,12 @@ inline bool G1CollectedHeap::is_obj_dead_full(const oop obj) const {
|
||||
}
|
||||
|
||||
inline void G1CollectedHeap::set_humongous_reclaim_candidate(uint region, bool value) {
|
||||
assert(_hrm->at(region)->is_starts_humongous(), "Must start a humongous object");
|
||||
assert(_hrm.at(region)->is_starts_humongous(), "Must start a humongous object");
|
||||
_humongous_reclaim_candidates.set_candidate(region, value);
|
||||
}
|
||||
|
||||
inline bool G1CollectedHeap::is_humongous_reclaim_candidate(uint region) {
|
||||
assert(_hrm->at(region)->is_starts_humongous(), "Must start a humongous object");
|
||||
assert(_hrm.at(region)->is_starts_humongous(), "Must start a humongous object");
|
||||
return _humongous_reclaim_candidates.is_candidate(region);
|
||||
}
|
||||
|
||||
|
@ -597,14 +597,14 @@ void G1HeapVerifier::verify_region_sets() {
|
||||
assert_heap_locked_or_at_safepoint(true /* should_be_vm_thread */);
|
||||
|
||||
// First, check the explicit lists.
|
||||
_g1h->_hrm->verify();
|
||||
_g1h->_hrm.verify();
|
||||
|
||||
// Finally, make sure that the region accounting in the lists is
|
||||
// consistent with what we see in the heap.
|
||||
|
||||
VerifyRegionListsClosure cl(&_g1h->_old_set, &_g1h->_archive_set, &_g1h->_humongous_set, _g1h->_hrm);
|
||||
VerifyRegionListsClosure cl(&_g1h->_old_set, &_g1h->_archive_set, &_g1h->_humongous_set, &_g1h->_hrm);
|
||||
_g1h->heap_region_iterate(&cl);
|
||||
cl.verify_counts(&_g1h->_old_set, &_g1h->_archive_set, &_g1h->_humongous_set, _g1h->_hrm);
|
||||
cl.verify_counts(&_g1h->_old_set, &_g1h->_archive_set, &_g1h->_humongous_set, &_g1h->_hrm);
|
||||
}
|
||||
|
||||
void G1HeapVerifier::prepare_for_verify() {
|
||||
@ -845,7 +845,7 @@ public:
|
||||
|
||||
bool G1HeapVerifier::check_region_attr_table() {
|
||||
G1CheckRegionAttrTableClosure cl;
|
||||
_g1h->_hrm->iterate(&cl);
|
||||
_g1h->_hrm.iterate(&cl);
|
||||
return !cl.failures();
|
||||
}
|
||||
#endif // PRODUCT
|
||||
|
@ -1,58 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "precompiled.hpp"
|
||||
#include "gc/g1/g1CollectedHeap.hpp"
|
||||
#include "gc/g1/g1HeterogeneousHeapPolicy.hpp"
|
||||
#include "gc/g1/g1Policy.hpp"
|
||||
#include "gc/g1/heterogeneousHeapRegionManager.hpp"
|
||||
|
||||
G1HeterogeneousHeapPolicy::G1HeterogeneousHeapPolicy(STWGCTimer* gc_timer) :
|
||||
G1Policy(gc_timer), _manager(NULL) {}
|
||||
|
||||
// We call the super class init(), after which we provision young_list_target_length() regions in dram.
|
||||
void G1HeterogeneousHeapPolicy::init(G1CollectedHeap* g1h, G1CollectionSet* collection_set) {
|
||||
G1Policy::init(g1h, collection_set);
|
||||
_manager = HeterogeneousHeapRegionManager::manager();
|
||||
_manager->adjust_dram_regions((uint)young_list_target_length(), G1CollectedHeap::heap()->workers());
|
||||
}
|
||||
|
||||
// After a collection pause, young list target length is updated. So we need to make sure we have enough regions in dram for young gen.
|
||||
void G1HeterogeneousHeapPolicy::record_collection_pause_end(double pause_time_ms, bool concurrent_operation_is_full_mark) {
|
||||
G1Policy::record_collection_pause_end(pause_time_ms, concurrent_operation_is_full_mark);
|
||||
_manager->adjust_dram_regions((uint)young_list_target_length(), G1CollectedHeap::heap()->workers());
|
||||
}
|
||||
|
||||
// After a full collection, young list target length is updated. So we need to make sure we have enough regions in dram for young gen.
|
||||
void G1HeterogeneousHeapPolicy::record_full_collection_end() {
|
||||
G1Policy::record_full_collection_end();
|
||||
_manager->adjust_dram_regions((uint)young_list_target_length(), G1CollectedHeap::heap()->workers());
|
||||
}
|
||||
|
||||
bool G1HeterogeneousHeapPolicy::force_upgrade_to_full() {
|
||||
if (_manager->has_borrowed_regions()) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
@ -1,47 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SHARE_GC_G1_G1HETEROGENEOUSHEAPPOLICY_HPP
|
||||
#define SHARE_GC_G1_G1HETEROGENEOUSHEAPPOLICY_HPP
|
||||
|
||||
#include "gc/g1/g1Policy.hpp"
|
||||
#include "gc/g1/heterogeneousHeapRegionManager.hpp"
|
||||
|
||||
class G1HeterogeneousHeapPolicy : public G1Policy {
|
||||
// Stash a pointer to the hrm.
|
||||
HeterogeneousHeapRegionManager* _manager;
|
||||
|
||||
public:
|
||||
G1HeterogeneousHeapPolicy(STWGCTimer* gc_timer);
|
||||
|
||||
// initialize policy
|
||||
virtual void init(G1CollectedHeap* g1h, G1CollectionSet* collection_set);
|
||||
// Record end of an evacuation pause.
|
||||
virtual void record_collection_pause_end(double pause_time_ms, bool concurrent_operation_is_full_mark);
|
||||
// Record the end of full collection.
|
||||
virtual void record_full_collection_end();
|
||||
|
||||
virtual bool force_upgrade_to_full();
|
||||
};
|
||||
#endif // SHARE_GC_G1_G1HETEROGENEOUSHEAPPOLICY_HPP
|
@ -1,51 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "precompiled.hpp"
|
||||
#include "gc/g1/g1Arguments.hpp"
|
||||
#include "gc/g1/g1HeterogeneousHeapYoungGenSizer.hpp"
|
||||
#include "gc/g1/heapRegion.hpp"
|
||||
|
||||
G1HeterogeneousHeapYoungGenSizer::G1HeterogeneousHeapYoungGenSizer() : G1YoungGenSizer() {
|
||||
// will be used later when min and max young size is calculated.
|
||||
_max_young_length = (uint)(G1Arguments::reasonable_max_memory_for_young() / HeapRegion::GrainBytes);
|
||||
}
|
||||
|
||||
// Since heap is sized potentially to larger value accounting for dram + nvdimm, we need to limit
|
||||
// max young gen size to the available dram.
|
||||
// Call parent class method first and then adjust sizes based on available dram
|
||||
void G1HeterogeneousHeapYoungGenSizer::adjust_max_new_size(uint number_of_heap_regions) {
|
||||
G1YoungGenSizer::adjust_max_new_size(number_of_heap_regions);
|
||||
adjust_lengths_based_on_dram_memory();
|
||||
}
|
||||
|
||||
void G1HeterogeneousHeapYoungGenSizer::heap_size_changed(uint new_number_of_heap_regions) {
|
||||
G1YoungGenSizer::heap_size_changed(new_number_of_heap_regions);
|
||||
adjust_lengths_based_on_dram_memory();
|
||||
}
|
||||
|
||||
void G1HeterogeneousHeapYoungGenSizer::adjust_lengths_based_on_dram_memory() {
|
||||
_min_desired_young_length = MIN2(_min_desired_young_length, _max_young_length);
|
||||
_max_desired_young_length = MIN2(_max_desired_young_length, _max_young_length);
|
||||
}
|
@ -1,51 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SHARE_GC_G1_G1HETEROGENEOUSHEAPYOUNGGENSIZER_HPP
|
||||
#define SHARE_GC_G1_G1HETEROGENEOUSHEAPYOUNGGENSIZER_HPP
|
||||
|
||||
#include "gc/g1/g1YoungGenSizer.hpp"
|
||||
|
||||
// This class prevents the size of young generation of G1 heap to exceed dram
|
||||
// memory available. If set on command line, MaxRAM and MaxRAMFraction/MaxRAMPercentage
|
||||
// are used to determine the maximum size that young generation can grow.
|
||||
// Else we set the maximum size to 80% of dram available in the system.
|
||||
|
||||
class G1HeterogeneousHeapYoungGenSizer : public G1YoungGenSizer {
|
||||
private:
|
||||
// maximum no of regions that young generation can grow to. Calculated in constructor.
|
||||
uint _max_young_length;
|
||||
void adjust_lengths_based_on_dram_memory();
|
||||
|
||||
public:
|
||||
G1HeterogeneousHeapYoungGenSizer();
|
||||
|
||||
// Calculate the maximum length of the young gen given the number of regions
|
||||
// depending on the sizing algorithm.
|
||||
virtual void adjust_max_new_size(uint number_of_heap_regions);
|
||||
|
||||
virtual void heap_size_changed(uint new_number_of_heap_regions);
|
||||
};
|
||||
|
||||
#endif // SHARE_GC_G1_G1HETEROGENEOUSHEAPYOUNGGENSIZER_HPP
|
@ -101,12 +101,6 @@ size_t G1PageBasedVirtualSpace::uncommitted_size() const {
|
||||
return reserved_size() - committed_size();
|
||||
}
|
||||
|
||||
void G1PageBasedVirtualSpace::commit_and_set_special() {
|
||||
commit_internal(addr_to_page_index(_low_boundary), addr_to_page_index(_high_boundary));
|
||||
_special = true;
|
||||
_dirty.initialize(reserved_size()/_page_size);
|
||||
}
|
||||
|
||||
size_t G1PageBasedVirtualSpace::addr_to_page_index(char* addr) const {
|
||||
return (addr - _low_boundary) / _page_size;
|
||||
}
|
||||
|
@ -134,8 +134,6 @@ class G1PageBasedVirtualSpace {
|
||||
// Memory left to use/expand in this virtual space.
|
||||
size_t uncommitted_size() const;
|
||||
|
||||
void commit_and_set_special();
|
||||
|
||||
bool contains(const void* p) const;
|
||||
|
||||
MemRegion reserved() {
|
||||
|
@ -33,7 +33,6 @@
|
||||
#include "gc/g1/g1ConcurrentRefine.hpp"
|
||||
#include "gc/g1/g1ConcurrentRefineStats.hpp"
|
||||
#include "gc/g1/g1CollectionSetChooser.hpp"
|
||||
#include "gc/g1/g1HeterogeneousHeapPolicy.hpp"
|
||||
#include "gc/g1/g1HotCardCache.hpp"
|
||||
#include "gc/g1/g1IHOPControl.hpp"
|
||||
#include "gc/g1/g1GCPhaseTimes.hpp"
|
||||
@ -68,7 +67,7 @@ G1Policy::G1Policy(STWGCTimer* gc_timer) :
|
||||
_survivor_surv_rate_group(new G1SurvRateGroup()),
|
||||
_reserve_factor((double) G1ReservePercent / 100.0),
|
||||
_reserve_regions(0),
|
||||
_young_gen_sizer(G1YoungGenSizer::create_gen_sizer()),
|
||||
_young_gen_sizer(),
|
||||
_free_regions_at_end_of_collection(0),
|
||||
_rs_length(0),
|
||||
_rs_length_prediction(0),
|
||||
@ -88,15 +87,6 @@ G1Policy::G1Policy(STWGCTimer* gc_timer) :
|
||||
|
||||
G1Policy::~G1Policy() {
|
||||
delete _ihop_control;
|
||||
delete _young_gen_sizer;
|
||||
}
|
||||
|
||||
G1Policy* G1Policy::create_policy(STWGCTimer* gc_timer_stw) {
|
||||
if (G1Arguments::is_heterogeneous_heap()) {
|
||||
return new G1HeterogeneousHeapPolicy(gc_timer_stw);
|
||||
} else {
|
||||
return new G1Policy(gc_timer_stw);
|
||||
}
|
||||
}
|
||||
|
||||
G1CollectorState* G1Policy::collector_state() const { return _g1h->collector_state(); }
|
||||
@ -108,9 +98,9 @@ void G1Policy::init(G1CollectedHeap* g1h, G1CollectionSet* collection_set) {
|
||||
assert(Heap_lock->owned_by_self(), "Locking discipline.");
|
||||
|
||||
if (!use_adaptive_young_list_length()) {
|
||||
_young_list_fixed_length = _young_gen_sizer->min_desired_young_length();
|
||||
_young_list_fixed_length = _young_gen_sizer.min_desired_young_length();
|
||||
}
|
||||
_young_gen_sizer->adjust_max_new_size(_g1h->max_regions());
|
||||
_young_gen_sizer.adjust_max_new_size(_g1h->max_regions());
|
||||
|
||||
_free_regions_at_end_of_collection = _g1h->num_free_regions();
|
||||
|
||||
@ -184,7 +174,7 @@ void G1Policy::record_new_heap_size(uint new_number_of_regions) {
|
||||
// smaller than 1.0) we'll get 1.
|
||||
_reserve_regions = (uint) ceil(reserve_regions_d);
|
||||
|
||||
_young_gen_sizer->heap_size_changed(new_number_of_regions);
|
||||
_young_gen_sizer.heap_size_changed(new_number_of_regions);
|
||||
|
||||
_ihop_control->update_target_occupancy(new_number_of_regions * HeapRegion::GrainBytes);
|
||||
}
|
||||
@ -203,14 +193,14 @@ uint G1Policy::calculate_young_list_desired_min_length(uint base_min_length) con
|
||||
}
|
||||
desired_min_length += base_min_length;
|
||||
// make sure we don't go below any user-defined minimum bound
|
||||
return MAX2(_young_gen_sizer->min_desired_young_length(), desired_min_length);
|
||||
return MAX2(_young_gen_sizer.min_desired_young_length(), desired_min_length);
|
||||
}
|
||||
|
||||
uint G1Policy::calculate_young_list_desired_max_length() const {
|
||||
// Here, we might want to also take into account any additional
|
||||
// constraints (i.e., user-defined minimum bound). Currently, we
|
||||
// effectively don't set this bound.
|
||||
return _young_gen_sizer->max_desired_young_length();
|
||||
return _young_gen_sizer.max_desired_young_length();
|
||||
}
|
||||
|
||||
uint G1Policy::update_young_list_max_and_target_length() {
|
||||
@ -976,7 +966,7 @@ bool G1Policy::can_expand_young_list() const {
|
||||
}
|
||||
|
||||
bool G1Policy::use_adaptive_young_list_length() const {
|
||||
return _young_gen_sizer->use_adaptive_young_list_length();
|
||||
return _young_gen_sizer.use_adaptive_young_list_length();
|
||||
}
|
||||
|
||||
size_t G1Policy::desired_survivor_size(uint max_regions) const {
|
||||
|
@ -49,7 +49,6 @@ class G1CollectionSetChooser;
|
||||
class G1IHOPControl;
|
||||
class G1Analytics;
|
||||
class G1SurvivorRegions;
|
||||
class G1YoungGenSizer;
|
||||
class GCPolicyCounters;
|
||||
class STWGCTimer;
|
||||
|
||||
@ -95,7 +94,7 @@ class G1Policy: public CHeapObj<mtGC> {
|
||||
// for the first time during initialization.
|
||||
uint _reserve_regions;
|
||||
|
||||
G1YoungGenSizer* _young_gen_sizer;
|
||||
G1YoungGenSizer _young_gen_sizer;
|
||||
|
||||
uint _free_regions_at_end_of_collection;
|
||||
|
||||
@ -302,8 +301,6 @@ public:
|
||||
|
||||
virtual ~G1Policy();
|
||||
|
||||
static G1Policy* create_policy(STWGCTimer* gc_timer_stw);
|
||||
|
||||
G1CollectorState* collector_state() const;
|
||||
|
||||
G1GCPhaseTimes* phase_times() const;
|
||||
@ -316,7 +313,7 @@ public:
|
||||
// This should be called after the heap is resized.
|
||||
void record_new_heap_size(uint new_number_of_regions);
|
||||
|
||||
virtual void init(G1CollectedHeap* g1h, G1CollectionSet* collection_set);
|
||||
void init(G1CollectedHeap* g1h, G1CollectionSet* collection_set);
|
||||
|
||||
void note_gc_start();
|
||||
|
||||
@ -328,11 +325,11 @@ public:
|
||||
|
||||
// Record the start and end of an evacuation pause.
|
||||
void record_collection_pause_start(double start_time_sec);
|
||||
virtual void record_collection_pause_end(double pause_time_ms, bool concurrent_operation_is_full_mark);
|
||||
void record_collection_pause_end(double pause_time_ms, bool concurrent_operation_is_full_mark);
|
||||
|
||||
// Record the start and end of a full collection.
|
||||
void record_full_collection_start();
|
||||
virtual void record_full_collection_end();
|
||||
void record_full_collection_end();
|
||||
|
||||
// Must currently be called while the world is stopped.
|
||||
void record_concurrent_mark_init_end();
|
||||
@ -449,10 +446,6 @@ public:
|
||||
void update_max_gc_locker_expansion();
|
||||
|
||||
void update_survivors_policy();
|
||||
|
||||
virtual bool force_upgrade_to_full() {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // SHARE_GC_G1_G1POLICY_HPP
|
||||
|
@ -26,15 +26,11 @@
|
||||
#include "gc/g1/g1BiasedArray.hpp"
|
||||
#include "gc/g1/g1NUMA.hpp"
|
||||
#include "gc/g1/g1RegionToSpaceMapper.hpp"
|
||||
#include "logging/log.hpp"
|
||||
#include "memory/allocation.inline.hpp"
|
||||
#include "memory/virtualspace.hpp"
|
||||
#include "runtime/java.hpp"
|
||||
#include "runtime/os.inline.hpp"
|
||||
#include "services/memTracker.hpp"
|
||||
#include "utilities/align.hpp"
|
||||
#include "utilities/bitMap.inline.hpp"
|
||||
#include "utilities/formatBuffer.hpp"
|
||||
#include "utilities/powerOfTwo.hpp"
|
||||
|
||||
G1RegionToSpaceMapper::G1RegionToSpaceMapper(ReservedSpace rs,
|
||||
@ -212,144 +208,6 @@ void G1RegionToSpaceMapper::fire_on_commit(uint start_idx, size_t num_regions, b
|
||||
}
|
||||
}
|
||||
|
||||
static bool map_nvdimm_space(ReservedSpace rs) {
|
||||
assert(AllocateOldGenAt != NULL, "");
|
||||
int _backing_fd = os::create_file_for_heap(AllocateOldGenAt);
|
||||
if (_backing_fd == -1) {
|
||||
log_error(gc, init)("Could not create file for Old generation at location %s", AllocateOldGenAt);
|
||||
return false;
|
||||
}
|
||||
// commit this memory in nv-dimm
|
||||
char* ret = os::attempt_map_memory_to_file_at(rs.base(), rs.size(), _backing_fd);
|
||||
|
||||
if (ret != rs.base()) {
|
||||
if (ret != NULL) {
|
||||
os::unmap_memory(rs.base(), rs.size());
|
||||
}
|
||||
log_error(gc, init)("Error in mapping Old Gen to given AllocateOldGenAt = %s", AllocateOldGenAt);
|
||||
os::close(_backing_fd);
|
||||
return false;
|
||||
}
|
||||
|
||||
os::close(_backing_fd);
|
||||
return true;
|
||||
}
|
||||
|
||||
G1RegionToHeteroSpaceMapper::G1RegionToHeteroSpaceMapper(ReservedSpace rs,
|
||||
size_t actual_size,
|
||||
size_t page_size,
|
||||
size_t alloc_granularity,
|
||||
size_t commit_factor,
|
||||
MEMFLAGS type) :
|
||||
G1RegionToSpaceMapper(rs, actual_size, page_size, alloc_granularity, commit_factor, type),
|
||||
_rs(rs),
|
||||
_dram_mapper(NULL),
|
||||
_num_committed_dram(0),
|
||||
_num_committed_nvdimm(0),
|
||||
_start_index_of_dram(0),
|
||||
_page_size(page_size),
|
||||
_commit_factor(commit_factor),
|
||||
_type(type) {
|
||||
assert(actual_size == 2 * MaxHeapSize, "For 2-way heterogenuous heap, reserved space is two times MaxHeapSize");
|
||||
}
|
||||
|
||||
bool G1RegionToHeteroSpaceMapper::initialize() {
|
||||
// Since we need to re-map the reserved space - 'Xmx' to nv-dimm and 'Xmx' to dram, we need to release the reserved memory first.
|
||||
// Because on some OSes (e.g. Windows) you cannot do a file mapping on memory reserved with regular mapping.
|
||||
os::release_memory(_rs.base(), _rs.size());
|
||||
// First half of size Xmx is for nv-dimm.
|
||||
ReservedSpace rs_nvdimm = _rs.first_part(MaxHeapSize);
|
||||
assert(rs_nvdimm.base() == _rs.base(), "We should get the same base address");
|
||||
|
||||
// Second half of reserved memory is mapped to dram.
|
||||
ReservedSpace rs_dram = _rs.last_part(MaxHeapSize);
|
||||
|
||||
assert(rs_dram.size() == rs_nvdimm.size() && rs_nvdimm.size() == MaxHeapSize, "They all should be same");
|
||||
|
||||
// Reserve dram memory
|
||||
char* base = os::attempt_reserve_memory_at(rs_dram.base(), rs_dram.size());
|
||||
if (base != rs_dram.base()) {
|
||||
if (base != NULL) {
|
||||
os::release_memory(base, rs_dram.size());
|
||||
}
|
||||
log_error(gc, init)("Error in re-mapping memory on dram during G1 heterogenous memory initialization");
|
||||
return false;
|
||||
}
|
||||
|
||||
// We reserve and commit this entire space to NV-DIMM.
|
||||
if (!map_nvdimm_space(rs_nvdimm)) {
|
||||
log_error(gc, init)("Error in re-mapping memory to nv-dimm during G1 heterogenous memory initialization");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_region_granularity >= (_page_size * _commit_factor)) {
|
||||
_dram_mapper = new G1RegionsLargerThanCommitSizeMapper(rs_dram, rs_dram.size(), _page_size, _region_granularity, _commit_factor, _type);
|
||||
} else {
|
||||
_dram_mapper = new G1RegionsSmallerThanCommitSizeMapper(rs_dram, rs_dram.size(), _page_size, _region_granularity, _commit_factor, _type);
|
||||
}
|
||||
|
||||
_start_index_of_dram = (uint)(rs_nvdimm.size() / _region_granularity);
|
||||
return true;
|
||||
}
|
||||
|
||||
void G1RegionToHeteroSpaceMapper::commit_regions(uint start_idx, size_t num_regions, WorkGang* pretouch_gang) {
|
||||
uint end_idx = (start_idx + (uint)num_regions - 1);
|
||||
|
||||
uint num_dram = end_idx >= _start_index_of_dram ? MIN2((end_idx - _start_index_of_dram + 1), (uint)num_regions) : 0;
|
||||
uint num_nvdimm = (uint)num_regions - num_dram;
|
||||
|
||||
if (num_nvdimm > 0) {
|
||||
// We do not need to commit nv-dimm regions, since they are committed in the beginning.
|
||||
_num_committed_nvdimm += num_nvdimm;
|
||||
}
|
||||
if (num_dram > 0) {
|
||||
_dram_mapper->commit_regions(start_idx > _start_index_of_dram ? (start_idx - _start_index_of_dram) : 0, num_dram, pretouch_gang);
|
||||
_num_committed_dram += num_dram;
|
||||
}
|
||||
}
|
||||
|
||||
void G1RegionToHeteroSpaceMapper::uncommit_regions(uint start_idx, size_t num_regions) {
|
||||
uint end_idx = (start_idx + (uint)num_regions - 1);
|
||||
uint num_dram = end_idx >= _start_index_of_dram ? MIN2((end_idx - _start_index_of_dram + 1), (uint)num_regions) : 0;
|
||||
uint num_nvdimm = (uint)num_regions - num_dram;
|
||||
|
||||
if (num_nvdimm > 0) {
|
||||
// We do not uncommit memory for nv-dimm regions.
|
||||
_num_committed_nvdimm -= num_nvdimm;
|
||||
}
|
||||
|
||||
if (num_dram > 0) {
|
||||
_dram_mapper->uncommit_regions(start_idx > _start_index_of_dram ? (start_idx - _start_index_of_dram) : 0, num_dram);
|
||||
_num_committed_dram -= num_dram;
|
||||
}
|
||||
}
|
||||
|
||||
uint G1RegionToHeteroSpaceMapper::num_committed_dram() const {
|
||||
return _num_committed_dram;
|
||||
}
|
||||
|
||||
uint G1RegionToHeteroSpaceMapper::num_committed_nvdimm() const {
|
||||
return _num_committed_nvdimm;
|
||||
}
|
||||
|
||||
G1RegionToSpaceMapper* G1RegionToSpaceMapper::create_heap_mapper(ReservedSpace rs,
|
||||
size_t actual_size,
|
||||
size_t page_size,
|
||||
size_t region_granularity,
|
||||
size_t commit_factor,
|
||||
MEMFLAGS type) {
|
||||
if (AllocateOldGenAt != NULL) {
|
||||
G1RegionToHeteroSpaceMapper* mapper = new G1RegionToHeteroSpaceMapper(rs, actual_size, page_size, region_granularity, commit_factor, type);
|
||||
if (!mapper->initialize()) {
|
||||
delete mapper;
|
||||
return NULL;
|
||||
}
|
||||
return (G1RegionToSpaceMapper*)mapper;
|
||||
} else {
|
||||
return create_mapper(rs, actual_size, page_size, region_granularity, commit_factor, type);
|
||||
}
|
||||
}
|
||||
|
||||
G1RegionToSpaceMapper* G1RegionToSpaceMapper::create_mapper(ReservedSpace rs,
|
||||
size_t actual_size,
|
||||
size_t page_size,
|
||||
@ -362,7 +220,3 @@ G1RegionToSpaceMapper* G1RegionToSpaceMapper::create_mapper(ReservedSpace rs,
|
||||
return new G1RegionsSmallerThanCommitSizeMapper(rs, actual_size, page_size, region_granularity, commit_factor, type);
|
||||
}
|
||||
}
|
||||
|
||||
void G1RegionToSpaceMapper::commit_and_set_special() {
|
||||
_storage.commit_and_set_special();
|
||||
}
|
||||
|
@ -68,7 +68,6 @@ class G1RegionToSpaceMapper : public CHeapObj<mtGC> {
|
||||
|
||||
virtual ~G1RegionToSpaceMapper() {}
|
||||
|
||||
void commit_and_set_special();
|
||||
virtual void commit_regions(uint start_idx, size_t num_regions = 1, WorkGang* pretouch_workers = NULL) = 0;
|
||||
virtual void uncommit_regions(uint start_idx, size_t num_regions = 1) = 0;
|
||||
|
||||
@ -86,35 +85,6 @@ class G1RegionToSpaceMapper : public CHeapObj<mtGC> {
|
||||
size_t region_granularity,
|
||||
size_t byte_translation_factor,
|
||||
MEMFLAGS type);
|
||||
|
||||
static G1RegionToSpaceMapper* create_heap_mapper(ReservedSpace rs,
|
||||
size_t actual_size,
|
||||
size_t page_size,
|
||||
size_t region_granularity,
|
||||
size_t byte_translation_factor,
|
||||
MEMFLAGS type);
|
||||
};
|
||||
|
||||
// G1RegionToSpaceMapper implementation where
|
||||
// part of space is mapped to dram and part to nv-dimm
|
||||
class G1RegionToHeteroSpaceMapper : public G1RegionToSpaceMapper {
|
||||
private:
|
||||
ReservedSpace _rs;
|
||||
G1RegionToSpaceMapper* _dram_mapper;
|
||||
uint _num_committed_dram;
|
||||
uint _num_committed_nvdimm;
|
||||
uint _start_index_of_dram;
|
||||
size_t _page_size;
|
||||
size_t _commit_factor;
|
||||
MEMFLAGS _type;
|
||||
|
||||
public:
|
||||
G1RegionToHeteroSpaceMapper(ReservedSpace rs, size_t used_size, size_t page_size, size_t region_granularity, size_t commit_factor, MEMFLAGS type);
|
||||
bool initialize();
|
||||
uint num_committed_dram() const;
|
||||
uint num_committed_nvdimm() const;
|
||||
|
||||
virtual void commit_regions(uint start_idx, size_t num_regions = 1, WorkGang* pretouch_workers = NULL);
|
||||
virtual void uncommit_regions(uint start_idx, size_t num_regions = 1);
|
||||
};
|
||||
#endif // SHARE_GC_G1_G1REGIONTOSPACEMAPPER_HPP
|
||||
|
@ -24,7 +24,6 @@
|
||||
|
||||
#include "precompiled.hpp"
|
||||
#include "gc/g1/g1Arguments.hpp"
|
||||
#include "gc/g1/g1HeterogeneousHeapYoungGenSizer.hpp"
|
||||
#include "gc/g1/g1YoungGenSizer.hpp"
|
||||
#include "gc/g1/heapRegion.hpp"
|
||||
#include "logging/log.hpp"
|
||||
@ -130,11 +129,3 @@ void G1YoungGenSizer::heap_size_changed(uint new_number_of_heap_regions) {
|
||||
recalculate_min_max_young_length(new_number_of_heap_regions, &_min_desired_young_length,
|
||||
&_max_desired_young_length);
|
||||
}
|
||||
|
||||
G1YoungGenSizer* G1YoungGenSizer::create_gen_sizer() {
|
||||
if (G1Arguments::is_heterogeneous_heap()) {
|
||||
return new G1HeterogeneousHeapYoungGenSizer();
|
||||
} else {
|
||||
return new G1YoungGenSizer();
|
||||
}
|
||||
}
|
||||
|
@ -63,7 +63,7 @@
|
||||
//
|
||||
// NewSize and MaxNewSize override NewRatio. So, NewRatio is ignored if it is
|
||||
// combined with either NewSize or MaxNewSize. (A warning message is printed.)
|
||||
class G1YoungGenSizer : public CHeapObj<mtGC> {
|
||||
class G1YoungGenSizer {
|
||||
private:
|
||||
enum SizerKind {
|
||||
SizerDefaults,
|
||||
@ -78,6 +78,9 @@ private:
|
||||
// true otherwise.
|
||||
bool _use_adaptive_sizing;
|
||||
|
||||
uint _min_desired_young_length;
|
||||
uint _max_desired_young_length;
|
||||
|
||||
uint calculate_default_min_length(uint new_number_of_heap_regions);
|
||||
uint calculate_default_max_length(uint new_number_of_heap_regions);
|
||||
|
||||
@ -85,10 +88,6 @@ private:
|
||||
// given the number of heap regions depending on the kind of sizing algorithm.
|
||||
void recalculate_min_max_young_length(uint number_of_heap_regions, uint* min_young_length, uint* max_young_length);
|
||||
|
||||
protected:
|
||||
uint _min_desired_young_length;
|
||||
uint _max_desired_young_length;
|
||||
|
||||
public:
|
||||
G1YoungGenSizer();
|
||||
// Calculate the maximum length of the young gen given the number of regions
|
||||
@ -106,8 +105,6 @@ public:
|
||||
bool use_adaptive_young_list_length() const {
|
||||
return _use_adaptive_sizing;
|
||||
}
|
||||
|
||||
static G1YoungGenSizer* create_gen_sizer();
|
||||
};
|
||||
|
||||
#endif // SHARE_GC_G1_G1YOUNGGENSIZER_HPP
|
||||
|
@ -302,16 +302,7 @@
|
||||
"of getloadavg() at which G1 triggers a periodic GC. A load " \
|
||||
"above this value cancels a given periodic GC. A value of zero " \
|
||||
"disables this check.") \
|
||||
range(0.0, (double)max_uintx) \
|
||||
\
|
||||
product(uintx, G1YoungExpansionBufferPercent, 10, EXPERIMENTAL, \
|
||||
"When heterogenous heap is enabled by AllocateOldGenAt " \
|
||||
"option, after every GC, young gen is re-sized which " \
|
||||
"involves system calls to commit/uncommit memory. To " \
|
||||
"reduce these calls, we keep a buffer of extra regions to " \
|
||||
"absorb small changes in young gen length. This flag takes " \
|
||||
"the buffer size as an percentage of young gen length") \
|
||||
range(0, 100)
|
||||
range(0.0, (double)max_uintx)
|
||||
|
||||
// end of GC_G1_FLAGS
|
||||
|
||||
|
@ -30,7 +30,6 @@
|
||||
#include "gc/g1/heapRegion.hpp"
|
||||
#include "gc/g1/heapRegionManager.inline.hpp"
|
||||
#include "gc/g1/heapRegionSet.inline.hpp"
|
||||
#include "gc/g1/heterogeneousHeapRegionManager.hpp"
|
||||
#include "jfr/jfrEvents.hpp"
|
||||
#include "logging/logStream.hpp"
|
||||
#include "memory/allocation.hpp"
|
||||
@ -77,13 +76,6 @@ HeapRegionManager::HeapRegionManager() :
|
||||
_free_list("Free list", new MasterFreeRegionListChecker())
|
||||
{ }
|
||||
|
||||
HeapRegionManager* HeapRegionManager::create_manager(G1CollectedHeap* heap) {
|
||||
if (G1Arguments::is_heterogeneous_heap()) {
|
||||
return new HeterogeneousHeapRegionManager((uint)(G1Arguments::heap_max_size_bytes() / HeapRegion::GrainBytes) /*heap size as num of regions*/);
|
||||
}
|
||||
return new HeapRegionManager();
|
||||
}
|
||||
|
||||
void HeapRegionManager::initialize(G1RegionToSpaceMapper* heap_storage,
|
||||
G1RegionToSpaceMapper* prev_bitmap,
|
||||
G1RegionToSpaceMapper* next_bitmap,
|
||||
@ -669,7 +661,7 @@ void HeapRegionManager::verify_optional() {
|
||||
#endif // PRODUCT
|
||||
|
||||
HeapRegionClaimer::HeapRegionClaimer(uint n_workers) :
|
||||
_n_workers(n_workers), _n_regions(G1CollectedHeap::heap()->_hrm->_allocated_heapregions_length), _claims(NULL) {
|
||||
_n_workers(n_workers), _n_regions(G1CollectedHeap::heap()->_hrm._allocated_heapregions_length), _claims(NULL) {
|
||||
assert(n_workers > 0, "Need at least one worker.");
|
||||
uint* new_claims = NEW_C_HEAP_ARRAY(uint, _n_regions, mtGC);
|
||||
memset(new_claims, Unclaimed, sizeof(*_claims) * _n_regions);
|
||||
|
@ -135,7 +135,6 @@ class HeapRegionManager: public CHeapObj<mtGC> {
|
||||
// Checks the G1MemoryNodeManager to see if this region is on the preferred node.
|
||||
bool is_on_preferred_index(uint region_index, uint preferred_node_index);
|
||||
|
||||
protected:
|
||||
G1HeapRegionTable _regions;
|
||||
G1RegionToSpaceMapper* _heap_mapper;
|
||||
G1RegionToSpaceMapper* _prev_bitmap_mapper;
|
||||
@ -148,8 +147,8 @@ protected:
|
||||
HeapRegion* new_heap_region(uint hrm_index);
|
||||
|
||||
// Humongous allocation helpers
|
||||
virtual HeapRegion* allocate_humongous_from_free_list(uint num_regions);
|
||||
virtual HeapRegion* allocate_humongous_allow_expand(uint num_regions);
|
||||
HeapRegion* allocate_humongous_from_free_list(uint num_regions);
|
||||
HeapRegion* allocate_humongous_allow_expand(uint num_regions);
|
||||
|
||||
// Expand helper for cases when the regions to expand are well defined.
|
||||
void expand_exact(uint start, uint num_regions, WorkGang* pretouch_workers);
|
||||
@ -162,25 +161,18 @@ public:
|
||||
// Empty constructor, we'll initialize it with the initialize() method.
|
||||
HeapRegionManager();
|
||||
|
||||
static HeapRegionManager* create_manager(G1CollectedHeap* heap);
|
||||
|
||||
virtual void initialize(G1RegionToSpaceMapper* heap_storage,
|
||||
G1RegionToSpaceMapper* prev_bitmap,
|
||||
G1RegionToSpaceMapper* next_bitmap,
|
||||
G1RegionToSpaceMapper* bot,
|
||||
G1RegionToSpaceMapper* cardtable,
|
||||
G1RegionToSpaceMapper* card_counts);
|
||||
|
||||
// Prepare heap regions before and after full collection.
|
||||
// Nothing to be done in this class.
|
||||
virtual void prepare_for_full_collection_start() {}
|
||||
virtual void prepare_for_full_collection_end() {}
|
||||
void initialize(G1RegionToSpaceMapper* heap_storage,
|
||||
G1RegionToSpaceMapper* prev_bitmap,
|
||||
G1RegionToSpaceMapper* next_bitmap,
|
||||
G1RegionToSpaceMapper* bot,
|
||||
G1RegionToSpaceMapper* cardtable,
|
||||
G1RegionToSpaceMapper* card_counts);
|
||||
|
||||
// Return the "dummy" region used for G1AllocRegion. This is currently a hardwired
|
||||
// new HeapRegion that owns HeapRegion at index 0. Since at the moment we commit
|
||||
// the heap from the lowest address, this region (and its associated data
|
||||
// structures) are available and we do not need to check further.
|
||||
virtual HeapRegion* get_dummy_region() { return new_heap_region(0); }
|
||||
HeapRegion* get_dummy_region() { return new_heap_region(0); }
|
||||
|
||||
// Return the HeapRegion at the given index. Assume that the index
|
||||
// is valid.
|
||||
@ -213,7 +205,7 @@ public:
|
||||
}
|
||||
|
||||
// Allocate a free region with specific node index. If fails allocate with next node index.
|
||||
virtual HeapRegion* allocate_free_region(HeapRegionType type, uint requested_node_index);
|
||||
HeapRegion* allocate_free_region(HeapRegionType type, uint requested_node_index);
|
||||
|
||||
// Allocate a humongous object from the free list
|
||||
HeapRegion* allocate_humongous(uint num_regions);
|
||||
@ -251,7 +243,7 @@ public:
|
||||
uint reserved_length() const { return (uint)_regions.length(); }
|
||||
|
||||
// Return maximum number of regions that heap can expand to.
|
||||
virtual uint max_length() const { return reserved_length(); }
|
||||
uint max_length() const { return reserved_length(); }
|
||||
|
||||
MemoryUsage get_auxiliary_data_memory_usage() const;
|
||||
|
||||
@ -261,22 +253,22 @@ public:
|
||||
// HeapRegions, or re-use existing ones. Returns the number of regions the
|
||||
// sequence was expanded by. If a HeapRegion allocation fails, the resulting
|
||||
// number of regions might be smaller than what's desired.
|
||||
virtual uint expand_by(uint num_regions, WorkGang* pretouch_workers);
|
||||
uint expand_by(uint num_regions, WorkGang* pretouch_workers);
|
||||
|
||||
// Makes sure that the regions from start to start+num_regions-1 are available
|
||||
// for allocation. Returns the number of regions that were committed to achieve
|
||||
// this.
|
||||
virtual uint expand_at(uint start, uint num_regions, WorkGang* pretouch_workers);
|
||||
uint expand_at(uint start, uint num_regions, WorkGang* pretouch_workers);
|
||||
|
||||
// Try to expand on the given node index, returning the index of the new region.
|
||||
virtual uint expand_on_preferred_node(uint node_index);
|
||||
uint expand_on_preferred_node(uint node_index);
|
||||
|
||||
HeapRegion* next_region_in_heap(const HeapRegion* r) const;
|
||||
|
||||
// Find the highest free or uncommitted region in the reserved heap,
|
||||
// and if uncommitted, commit it. If none are available, return G1_NO_HRM_INDEX.
|
||||
// Set the 'expanded' boolean true if a new region was committed.
|
||||
virtual uint find_highest_free(bool* expanded);
|
||||
uint find_highest_free(bool* expanded);
|
||||
|
||||
// Allocate the regions that contain the address range specified, committing the
|
||||
// regions if necessary. Return false if any of the regions is already committed
|
||||
@ -291,13 +283,13 @@ public:
|
||||
|
||||
// Uncommit up to num_regions_to_remove regions that are completely free.
|
||||
// Return the actual number of uncommitted regions.
|
||||
virtual uint shrink_by(uint num_regions_to_remove);
|
||||
uint shrink_by(uint num_regions_to_remove);
|
||||
|
||||
// Uncommit a number of regions starting at the specified index, which must be available,
|
||||
// empty, and free.
|
||||
void shrink_at(uint index, size_t num_regions);
|
||||
|
||||
virtual void verify();
|
||||
void verify();
|
||||
|
||||
// Do some sanity checking.
|
||||
void verify_optional() PRODUCT_RETURN;
|
||||
|
@ -287,21 +287,6 @@ void FreeRegionList::remove_starting_at(HeapRegion* first, uint num_regions) {
|
||||
verify_optional();
|
||||
}
|
||||
|
||||
uint FreeRegionList::num_of_regions_in_range(uint start, uint end) const {
|
||||
HeapRegion* cur = _head;
|
||||
uint num = 0;
|
||||
while (cur != NULL) {
|
||||
uint index = cur->hrm_index();
|
||||
if (index > end) {
|
||||
break;
|
||||
} else if (index >= start) {
|
||||
num++;
|
||||
}
|
||||
cur = cur->next();
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
void FreeRegionList::verify() {
|
||||
// See comment in HeapRegionSetBase::verify() about MT safety and
|
||||
// verification.
|
||||
|
@ -234,8 +234,6 @@ public:
|
||||
|
||||
virtual void verify();
|
||||
|
||||
uint num_of_regions_in_range(uint start, uint end) const;
|
||||
|
||||
using HeapRegionSetBase::length;
|
||||
uint length(uint node_index) const;
|
||||
};
|
||||
|
@ -117,7 +117,7 @@ private:
|
||||
_tag = tag;
|
||||
}
|
||||
|
||||
// Private constructor used static constants
|
||||
// Private constructor used for static constants
|
||||
HeapRegionType(Tag t) : _tag(t) { hrt_assert_is_valid(_tag); }
|
||||
|
||||
public:
|
||||
|
@ -1,533 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "precompiled.hpp"
|
||||
#include "gc/g1/g1CollectedHeap.inline.hpp"
|
||||
#include "gc/g1/g1ConcurrentRefine.hpp"
|
||||
#include "gc/g1/heapRegion.hpp"
|
||||
#include "gc/g1/heapRegionManager.inline.hpp"
|
||||
#include "gc/g1/heapRegionSet.inline.hpp"
|
||||
#include "gc/g1/heterogeneousHeapRegionManager.hpp"
|
||||
#include "memory/allocation.hpp"
|
||||
|
||||
|
||||
HeterogeneousHeapRegionManager* HeterogeneousHeapRegionManager::manager() {
|
||||
G1CollectedHeap* g1h = G1CollectedHeap::heap();
|
||||
assert(g1h != NULL, "Uninitialized access to HeterogeneousHeapRegionManager::manager()");
|
||||
|
||||
HeapRegionManager* hrm = g1h->hrm();
|
||||
assert(hrm != NULL, "Uninitialized access to HeterogeneousHeapRegionManager::manager()");
|
||||
return (HeterogeneousHeapRegionManager*)hrm;
|
||||
}
|
||||
|
||||
void HeterogeneousHeapRegionManager::initialize(G1RegionToSpaceMapper* heap_storage,
|
||||
G1RegionToSpaceMapper* prev_bitmap,
|
||||
G1RegionToSpaceMapper* next_bitmap,
|
||||
G1RegionToSpaceMapper* bot,
|
||||
G1RegionToSpaceMapper* cardtable,
|
||||
G1RegionToSpaceMapper* card_counts) {
|
||||
HeapRegionManager::initialize(heap_storage, prev_bitmap, next_bitmap, bot, cardtable, card_counts);
|
||||
|
||||
// We commit bitmap for all regions during initialization and mark the bitmap space as special.
|
||||
// This allows regions to be un-committed while concurrent-marking threads are accessing the bitmap concurrently.
|
||||
_prev_bitmap_mapper->commit_and_set_special();
|
||||
_next_bitmap_mapper->commit_and_set_special();
|
||||
}
|
||||
|
||||
// expand_by() is called to grow the heap. We grow into nvdimm now.
|
||||
// Dram regions are committed later as needed during mutator region allocation or
|
||||
// when young list target length is determined after gc cycle.
|
||||
uint HeterogeneousHeapRegionManager::expand_by(uint num_regions, WorkGang* pretouch_workers) {
|
||||
uint num_regions_possible = total_regions_committed() >= max_length() ? 0 : max_length() - total_regions_committed();
|
||||
uint num_expanded = expand_nvdimm(MIN2(num_regions, num_regions_possible), pretouch_workers);
|
||||
return num_expanded;
|
||||
}
|
||||
|
||||
// Expands heap starting from 'start' index. The question is should we expand from one memory (e.g. nvdimm) to another (e.g. dram).
|
||||
// Looking at the code, expand_at() is called for humongous allocation where 'start' is in nv-dimm.
|
||||
// So we only allocate regions in the same kind of memory as 'start'.
|
||||
uint HeterogeneousHeapRegionManager::expand_at(uint start, uint num_regions, WorkGang* pretouch_workers) {
|
||||
if (num_regions == 0) {
|
||||
return 0;
|
||||
}
|
||||
uint target_num_regions = MIN2(num_regions, max_length() - total_regions_committed());
|
||||
uint end = is_in_nvdimm(start) ? end_index_of_nvdimm() : end_index_of_dram();
|
||||
|
||||
uint num_expanded = expand_in_range(start, end, target_num_regions, pretouch_workers);
|
||||
assert(total_regions_committed() <= max_length(), "must be");
|
||||
return num_expanded;
|
||||
}
|
||||
|
||||
// This function ensures that there are 'expected_num_regions' committed regions in dram.
|
||||
// If new regions are committed, it un-commits that many regions from nv-dimm.
|
||||
// If there are already more regions committed in dram, extra regions are un-committed.
|
||||
void HeterogeneousHeapRegionManager::adjust_dram_regions(uint expected_num_regions, WorkGang* pretouch_workers) {
|
||||
|
||||
// Release back the extra regions allocated in evacuation failure scenario.
|
||||
if(_no_borrowed_regions > 0) {
|
||||
_no_borrowed_regions -= shrink_dram(_no_borrowed_regions);
|
||||
_no_borrowed_regions -= shrink_nvdimm(_no_borrowed_regions);
|
||||
}
|
||||
|
||||
if(expected_num_regions > free_list_dram_length()) {
|
||||
// If we are going to expand DRAM, we expand a little more so that we can absorb small variations in Young gen sizing.
|
||||
uint targeted_dram_regions = expected_num_regions * (1 + (double)G1YoungExpansionBufferPercent / 100);
|
||||
uint to_be_made_available = targeted_dram_regions - free_list_dram_length();
|
||||
|
||||
#ifdef ASSERT
|
||||
uint total_committed_before = total_regions_committed();
|
||||
#endif
|
||||
uint can_be_made_available = shrink_nvdimm(to_be_made_available);
|
||||
uint ret = expand_dram(can_be_made_available, pretouch_workers);
|
||||
#ifdef ASSERT
|
||||
assert(ret == can_be_made_available, "should be equal");
|
||||
assert(total_committed_before == total_regions_committed(), "invariant not met");
|
||||
#endif
|
||||
} else {
|
||||
uint to_be_released = free_list_dram_length() - expected_num_regions;
|
||||
// if number of extra DRAM regions is small, do not shrink.
|
||||
if (to_be_released < expected_num_regions * G1YoungExpansionBufferPercent / 100) {
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef ASSERT
|
||||
uint total_committed_before = total_regions_committed();
|
||||
#endif
|
||||
uint ret = shrink_dram(to_be_released);
|
||||
assert(ret == to_be_released, "Should be able to shrink by given amount");
|
||||
ret = expand_nvdimm(to_be_released, pretouch_workers);
|
||||
#ifdef ASSERT
|
||||
assert(ret == to_be_released, "Should be able to expand by given amount");
|
||||
assert(total_committed_before == total_regions_committed(), "invariant not met");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
uint HeterogeneousHeapRegionManager::total_regions_committed() const {
|
||||
return num_committed_dram() + num_committed_nvdimm();
|
||||
}
|
||||
|
||||
uint HeterogeneousHeapRegionManager::num_committed_dram() const {
|
||||
// This class does not keep count of committed regions in dram and nv-dimm.
|
||||
// G1RegionToHeteroSpaceMapper keeps this information.
|
||||
return static_cast<G1RegionToHeteroSpaceMapper*>(_heap_mapper)->num_committed_dram();
|
||||
}
|
||||
|
||||
uint HeterogeneousHeapRegionManager::num_committed_nvdimm() const {
|
||||
// See comment for num_committed_dram()
|
||||
return static_cast<G1RegionToHeteroSpaceMapper*>(_heap_mapper)->num_committed_nvdimm();
|
||||
}
|
||||
|
||||
// Return maximum number of regions that heap can expand to.
|
||||
uint HeterogeneousHeapRegionManager::max_length() const {
|
||||
return _max_regions;
|
||||
}
|
||||
|
||||
uint HeterogeneousHeapRegionManager::find_unavailable_in_range(uint start_idx, uint end_idx, uint* res_idx) const {
|
||||
guarantee(res_idx != NULL, "checking");
|
||||
guarantee(start_idx <= (reserved_length() + 1), "checking");
|
||||
|
||||
uint num_regions = 0;
|
||||
|
||||
uint cur = start_idx;
|
||||
while (cur <= end_idx && is_available(cur)) {
|
||||
cur++;
|
||||
}
|
||||
if (cur == end_idx + 1) {
|
||||
return num_regions;
|
||||
}
|
||||
*res_idx = cur;
|
||||
while (cur <= end_idx && !is_available(cur)) {
|
||||
cur++;
|
||||
}
|
||||
num_regions = cur - *res_idx;
|
||||
|
||||
#ifdef ASSERT
|
||||
for (uint i = *res_idx; i < (*res_idx + num_regions); i++) {
|
||||
assert(!is_available(i), "just checking");
|
||||
}
|
||||
assert(cur == end_idx + 1 || num_regions == 0 || is_available(cur),
|
||||
"The region at the current position %u must be available or at the end", cur);
|
||||
#endif
|
||||
return num_regions;
|
||||
}
|
||||
|
||||
uint HeterogeneousHeapRegionManager::expand_dram(uint num_regions, WorkGang* pretouch_workers) {
|
||||
return expand_in_range(start_index_of_dram(), end_index_of_dram(), num_regions, pretouch_workers);
|
||||
}
|
||||
|
||||
uint HeterogeneousHeapRegionManager::expand_nvdimm(uint num_regions, WorkGang* pretouch_workers) {
|
||||
return expand_in_range(start_index_of_nvdimm(), end_index_of_nvdimm(), num_regions, pretouch_workers);
|
||||
}
|
||||
|
||||
// Follows same logic as expand_at() form HeapRegionManager.
|
||||
uint HeterogeneousHeapRegionManager::expand_in_range(uint start, uint end, uint num_regions, WorkGang* pretouch_gang) {
|
||||
|
||||
uint so_far = 0;
|
||||
uint chunk_start = 0;
|
||||
uint num_last_found = 0;
|
||||
while (so_far < num_regions &&
|
||||
(num_last_found = find_unavailable_in_range(start, end, &chunk_start)) > 0) {
|
||||
uint to_commit = MIN2(num_regions - so_far, num_last_found);
|
||||
make_regions_available(chunk_start, to_commit, pretouch_gang);
|
||||
so_far += to_commit;
|
||||
start = chunk_start + to_commit + 1;
|
||||
}
|
||||
|
||||
return so_far;
|
||||
}
|
||||
|
||||
// Shrink in the range of indexes which are reserved for dram.
|
||||
uint HeterogeneousHeapRegionManager::shrink_dram(uint num_regions, bool update_free_list) {
|
||||
return shrink_in_range(start_index_of_dram(), end_index_of_dram(), num_regions, update_free_list);
|
||||
}
|
||||
|
||||
// Shrink in the range of indexes which are reserved for nv-dimm.
|
||||
uint HeterogeneousHeapRegionManager::shrink_nvdimm(uint num_regions, bool update_free_list) {
|
||||
return shrink_in_range(start_index_of_nvdimm(), end_index_of_nvdimm(), num_regions, update_free_list);
|
||||
}
|
||||
|
||||
// Find empty regions in given range, un-commit them and return the count.
|
||||
uint HeterogeneousHeapRegionManager::shrink_in_range(uint start, uint end, uint num_regions, bool update_free_list) {
|
||||
|
||||
if (num_regions == 0) {
|
||||
return 0;
|
||||
}
|
||||
uint so_far = 0;
|
||||
uint idx_last_found = 0;
|
||||
uint num_last_found;
|
||||
while (so_far < num_regions &&
|
||||
(num_last_found = find_empty_in_range_reverse(start, end, &idx_last_found)) > 0) {
|
||||
uint to_uncommit = MIN2(num_regions - so_far, num_last_found);
|
||||
if(update_free_list) {
|
||||
_free_list.remove_starting_at(at(idx_last_found + num_last_found - to_uncommit), to_uncommit);
|
||||
}
|
||||
uncommit_regions(idx_last_found + num_last_found - to_uncommit, to_uncommit);
|
||||
so_far += to_uncommit;
|
||||
end = idx_last_found;
|
||||
}
|
||||
return so_far;
|
||||
}
|
||||
|
||||
uint HeterogeneousHeapRegionManager::find_empty_in_range_reverse(uint start_idx, uint end_idx, uint* res_idx) {
|
||||
guarantee(res_idx != NULL, "checking");
|
||||
guarantee(start_idx < reserved_length(), "checking");
|
||||
guarantee(end_idx < reserved_length(), "checking");
|
||||
if(start_idx > end_idx) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint num_regions_found = 0;
|
||||
|
||||
jlong cur = end_idx;
|
||||
while (cur >= start_idx && !(is_available(cur) && at(cur)->is_empty())) {
|
||||
cur--;
|
||||
}
|
||||
if (cur == start_idx - 1) {
|
||||
return num_regions_found;
|
||||
}
|
||||
jlong old_cur = cur;
|
||||
// cur indexes the first empty region
|
||||
while (cur >= start_idx && is_available(cur) && at(cur)->is_empty()) {
|
||||
cur--;
|
||||
}
|
||||
*res_idx = cur + 1;
|
||||
num_regions_found = old_cur - cur;
|
||||
|
||||
#ifdef ASSERT
|
||||
for (uint i = *res_idx; i < (*res_idx + num_regions_found); i++) {
|
||||
assert(at(i)->is_empty(), "just checking");
|
||||
}
|
||||
#endif
|
||||
return num_regions_found;
|
||||
}
|
||||
|
||||
HeapRegion* HeterogeneousHeapRegionManager::allocate_free_region(HeapRegionType type, uint node_index) {
|
||||
|
||||
// We want to prevent mutators from proceeding when we have borrowed regions from the last collection. This
|
||||
// will force a full collection to remedy the situation.
|
||||
// Free region requests from GC threads can proceed.
|
||||
if(type.is_eden() || type.is_humongous()) {
|
||||
if(has_borrowed_regions()) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// old and humongous regions are allocated from nv-dimm; eden and survivor regions are allocated from dram
|
||||
// assumption: dram regions take higher indexes
|
||||
bool from_nvdimm = (type.is_old() || type.is_humongous()) ? true : false;
|
||||
bool from_head = from_nvdimm;
|
||||
HeapRegion* hr = _free_list.remove_region(from_head);
|
||||
|
||||
if (hr != NULL && ( (from_nvdimm && !is_in_nvdimm(hr->hrm_index())) || (!from_nvdimm && !is_in_dram(hr->hrm_index())) ) ) {
|
||||
_free_list.add_ordered(hr);
|
||||
hr = NULL;
|
||||
}
|
||||
|
||||
#ifdef ASSERT
|
||||
uint total_committed_before = total_regions_committed();
|
||||
#endif
|
||||
|
||||
if (hr == NULL) {
|
||||
if (!from_nvdimm) {
|
||||
uint ret = shrink_nvdimm(1);
|
||||
if (ret == 1) {
|
||||
ret = expand_dram(1, NULL);
|
||||
assert(ret == 1, "We should be able to commit one region");
|
||||
hr = _free_list.remove_region(from_head);
|
||||
}
|
||||
}
|
||||
else { /*is_old*/
|
||||
uint ret = shrink_dram(1);
|
||||
if (ret == 1) {
|
||||
ret = expand_nvdimm(1, NULL);
|
||||
assert(ret == 1, "We should be able to commit one region");
|
||||
hr = _free_list.remove_region(from_head);
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef ASSERT
|
||||
assert(total_committed_before == total_regions_committed(), "invariant not met");
|
||||
#endif
|
||||
|
||||
// When an old region is requested (which happens during collection pause) and we can't find any empty region
|
||||
// in the set of available regions (which is an evacuation failure scenario), we borrow (or pre-allocate) an unavailable region
|
||||
// from nv-dimm. This region is used to evacuate surviving objects from eden, survivor or old.
|
||||
if(hr == NULL && type.is_old()) {
|
||||
hr = borrow_old_region_for_gc();
|
||||
}
|
||||
|
||||
if (hr != NULL) {
|
||||
assert(hr->next() == NULL, "Single region should not have next");
|
||||
assert(is_available(hr->hrm_index()), "Must be committed");
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
HeapRegion* HeterogeneousHeapRegionManager::allocate_humongous_from_free_list(uint num_regions) {
|
||||
if (has_borrowed_regions()) {
|
||||
return NULL;
|
||||
}
|
||||
uint candidate = find_contiguous(start_index_of_nvdimm(), end_index_of_nvdimm(), num_regions, true);
|
||||
if (candidate == G1_NO_HRM_INDEX) {
|
||||
return NULL;
|
||||
}
|
||||
return allocate_free_regions_starting_at(candidate, num_regions);
|
||||
}
|
||||
|
||||
HeapRegion* HeterogeneousHeapRegionManager::allocate_humongous_allow_expand(uint num_regions) {
|
||||
if (has_borrowed_regions()) {
|
||||
return NULL;
|
||||
}
|
||||
uint candidate = find_contiguous(start_index_of_nvdimm(), end_index_of_nvdimm(), num_regions, false);
|
||||
if (candidate == G1_NO_HRM_INDEX) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
expand_exact(candidate, num_regions, NULL);
|
||||
return allocate_free_regions_starting_at(candidate, num_regions);
|
||||
}
|
||||
|
||||
uint HeterogeneousHeapRegionManager::find_contiguous(size_t start, size_t end, size_t num, bool empty_only) {
|
||||
uint found = 0;
|
||||
size_t length_found = 0;
|
||||
uint cur = (uint)start;
|
||||
uint length_unavailable = 0;
|
||||
|
||||
while (length_found < num && cur <= end) {
|
||||
HeapRegion* hr = _regions.get_by_index(cur);
|
||||
if ((!empty_only && !is_available(cur)) || (is_available(cur) && hr != NULL && hr->is_empty())) {
|
||||
// This region is a potential candidate for allocation into.
|
||||
if (!is_available(cur)) {
|
||||
if(shrink_dram(1) == 1) {
|
||||
uint ret = expand_in_range(cur, cur, 1, NULL);
|
||||
assert(ret == 1, "We should be able to expand at this index");
|
||||
} else {
|
||||
length_unavailable++;
|
||||
}
|
||||
}
|
||||
length_found++;
|
||||
}
|
||||
else {
|
||||
// This region is not a candidate. The next region is the next possible one.
|
||||
found = cur + 1;
|
||||
length_found = 0;
|
||||
}
|
||||
cur++;
|
||||
}
|
||||
|
||||
if (length_found == num) {
|
||||
for (uint i = found; i < (found + num); i++) {
|
||||
HeapRegion* hr = _regions.get_by_index(i);
|
||||
// sanity check
|
||||
guarantee((!empty_only && !is_available(i)) || (is_available(i) && hr != NULL && hr->is_empty()),
|
||||
"Found region sequence starting at " UINT32_FORMAT ", length " SIZE_FORMAT
|
||||
" that is not empty at " UINT32_FORMAT ". Hr is " PTR_FORMAT, found, num, i, p2i(hr));
|
||||
}
|
||||
if (!empty_only && length_unavailable > (max_length() - total_regions_committed())) {
|
||||
// if 'length_unavailable' number of regions will be made available, we will exceed max regions.
|
||||
return G1_NO_HRM_INDEX;
|
||||
}
|
||||
return found;
|
||||
}
|
||||
else {
|
||||
return G1_NO_HRM_INDEX;
|
||||
}
|
||||
}
|
||||
|
||||
uint HeterogeneousHeapRegionManager::find_highest_free(bool* expanded) {
|
||||
// Loop downwards from the highest dram region index, looking for an
|
||||
// entry which is either free or not yet committed. If not yet
|
||||
// committed, expand_at that index.
|
||||
uint curr = end_index_of_dram();
|
||||
while (true) {
|
||||
HeapRegion *hr = _regions.get_by_index(curr);
|
||||
if (hr == NULL && !(total_regions_committed() < _max_regions)) {
|
||||
uint res = shrink_nvdimm(1);
|
||||
if (res == 1) {
|
||||
res = expand_in_range(curr, curr, 1, NULL);
|
||||
assert(res == 1, "We should be able to expand since shrink was successful");
|
||||
*expanded = true;
|
||||
return curr;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (hr->is_free()) {
|
||||
*expanded = false;
|
||||
return curr;
|
||||
}
|
||||
}
|
||||
if (curr == start_index_of_dram()) {
|
||||
return G1_NO_HRM_INDEX;
|
||||
}
|
||||
curr--;
|
||||
}
|
||||
}
|
||||
|
||||
// We need to override this since region 0 which serves are dummy region in base class may not be available here.
|
||||
// This is a corner condition when either number of regions is small. When adaptive sizing is used, initial heap size
|
||||
// could be just one region. This region is commited in dram to be used for young generation, leaving region 0 (which is in nvdimm)
|
||||
// unavailable.
|
||||
HeapRegion* HeterogeneousHeapRegionManager::get_dummy_region() {
|
||||
uint curr = 0;
|
||||
|
||||
while (curr < _regions.length()) {
|
||||
if (is_available(curr)) {
|
||||
return new_heap_region(curr);
|
||||
}
|
||||
curr++;
|
||||
}
|
||||
assert(false, "We should always find a region available for dummy region");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// First shrink in dram, then in nv-dimm.
|
||||
uint HeterogeneousHeapRegionManager::shrink_by(uint num_regions) {
|
||||
// This call is made at end of full collection. Before making this call the region sets are tore down (tear_down_region_sets()).
|
||||
// So shrink() calls below do not need to remove uncomitted regions from free list.
|
||||
uint ret = shrink_dram(num_regions, false /* update_free_list */);
|
||||
ret += shrink_nvdimm(num_regions - ret, false /* update_free_list */);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void HeterogeneousHeapRegionManager::verify() {
|
||||
HeapRegionManager::verify();
|
||||
}
|
||||
|
||||
uint HeterogeneousHeapRegionManager::free_list_dram_length() const {
|
||||
return _free_list.num_of_regions_in_range(start_index_of_dram(), end_index_of_dram());
|
||||
}
|
||||
|
||||
uint HeterogeneousHeapRegionManager::free_list_nvdimm_length() const {
|
||||
return _free_list.num_of_regions_in_range(start_index_of_nvdimm(), end_index_of_nvdimm());
|
||||
}
|
||||
|
||||
bool HeterogeneousHeapRegionManager::is_in_nvdimm(uint index) const {
|
||||
return index >= start_index_of_nvdimm() && index <= end_index_of_nvdimm();
|
||||
}
|
||||
|
||||
bool HeterogeneousHeapRegionManager::is_in_dram(uint index) const {
|
||||
return index >= start_index_of_dram() && index <= end_index_of_dram();
|
||||
}
|
||||
|
||||
// We have to make sure full collection copies all surviving objects to NV-DIMM.
|
||||
// We might not have enough regions in nvdimm_set, so we need to make more regions on NV-DIMM available for full collection.
|
||||
// Note: by doing this we are breaking the in-variant that total number of committed regions is equal to current heap size.
|
||||
// After full collection ends, we will re-establish this in-variant by freeing DRAM regions.
|
||||
void HeterogeneousHeapRegionManager::prepare_for_full_collection_start() {
|
||||
_total_commited_before_full_gc = total_regions_committed() - _no_borrowed_regions;
|
||||
_no_borrowed_regions = 0;
|
||||
expand_nvdimm(num_committed_dram(), NULL);
|
||||
remove_all_free_regions();
|
||||
}
|
||||
|
||||
// We need to bring back the total committed regions to before full collection start.
|
||||
// Unless we are close to OOM, all regular (not pinned) regions in DRAM should be free.
|
||||
// We shrink all free regions in DRAM and if needed from NV-DIMM (when there are pinned DRAM regions)
|
||||
// If we can't bring back committed regions count to _total_commited_before_full_gc, we keep the extra count in _no_borrowed_regions.
|
||||
// When this GC finishes, new regions won't be allocated since has_borrowed_regions() is true. VM will be forced to re-try GC
|
||||
// with clear soft references followed by OOM error in worst case.
|
||||
void HeterogeneousHeapRegionManager::prepare_for_full_collection_end() {
|
||||
uint shrink_size = total_regions_committed() - _total_commited_before_full_gc;
|
||||
uint so_far = 0;
|
||||
uint idx_last_found = 0;
|
||||
uint num_last_found;
|
||||
uint end = (uint)_regions.length() - 1;
|
||||
while (so_far < shrink_size &&
|
||||
(num_last_found = find_empty_in_range_reverse(0, end, &idx_last_found)) > 0) {
|
||||
uint to_uncommit = MIN2(shrink_size - so_far, num_last_found);
|
||||
uncommit_regions(idx_last_found + num_last_found - to_uncommit, to_uncommit);
|
||||
so_far += to_uncommit;
|
||||
end = idx_last_found;
|
||||
}
|
||||
// See comment above the function.
|
||||
_no_borrowed_regions = shrink_size - so_far;
|
||||
}
|
||||
|
||||
uint HeterogeneousHeapRegionManager::start_index_of_dram() const { return _max_regions;}
|
||||
|
||||
uint HeterogeneousHeapRegionManager::end_index_of_dram() const { return 2*_max_regions - 1; }
|
||||
|
||||
uint HeterogeneousHeapRegionManager::start_index_of_nvdimm() const { return 0; }
|
||||
|
||||
uint HeterogeneousHeapRegionManager::end_index_of_nvdimm() const { return _max_regions - 1; }
|
||||
|
||||
// This function is called when there are no free nv-dimm regions.
|
||||
// It borrows a region from the set of unavailable regions in nv-dimm for GC purpose.
|
||||
HeapRegion* HeterogeneousHeapRegionManager::borrow_old_region_for_gc() {
|
||||
assert(free_list_nvdimm_length() == 0, "this function should be called only when there are no nv-dimm regions in free list");
|
||||
|
||||
uint ret = expand_nvdimm(1, NULL);
|
||||
if(ret != 1) {
|
||||
return NULL;
|
||||
}
|
||||
HeapRegion* hr = _free_list.remove_region(true /*from_head*/);
|
||||
assert(is_in_nvdimm(hr->hrm_index()), "allocated region should be in nv-dimm");
|
||||
_no_borrowed_regions++;
|
||||
return hr;
|
||||
}
|
||||
|
||||
bool HeterogeneousHeapRegionManager::has_borrowed_regions() const {
|
||||
return _no_borrowed_regions > 0;
|
||||
}
|
@ -1,146 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SHARE_GC_G1_HETEROGENEOUSHEAPREGIONMANAGER_HPP
|
||||
#define SHARE_GC_G1_HETEROGENEOUSHEAPREGIONMANAGER_HPP
|
||||
|
||||
#include "gc/g1/heapRegionManager.hpp"
|
||||
|
||||
// This class manages heap regions on heterogenous memory comprising of dram and nv-dimm.
|
||||
// Regions in dram (dram_set) are used for young objects and archive regions (CDS).
|
||||
// Regions in nv-dimm (nvdimm_set) are used for old objects and humongous objects.
|
||||
// At any point there are some regions committed on dram and some on nv-dimm with the following guarantees:
|
||||
// 1. The total number of regions committed in dram and nv-dimm equals the current size of heap.
|
||||
// 2. Consequently, total number of regions committed is less than or equal to Xmx.
|
||||
// 3. To maintain the guarantee stated by 1., whenever one set grows (new regions committed), the other set shrinks (regions un-committed).
|
||||
// 3a. If more dram regions are needed (young generation expansion), corresponding number of regions in nv-dimm are un-committed.
|
||||
// 3b. When old generation or humongous set grows, and new regions need to be committed to nv-dimm, corresponding number of regions
|
||||
// are un-committed in dram.
|
||||
class HeterogeneousHeapRegionManager : public HeapRegionManager {
|
||||
const uint _max_regions;
|
||||
uint _max_dram_regions;
|
||||
uint _max_nvdimm_regions;
|
||||
uint _start_index_of_nvdimm;
|
||||
uint _total_commited_before_full_gc;
|
||||
uint _no_borrowed_regions;
|
||||
|
||||
uint total_regions_committed() const;
|
||||
uint num_committed_dram() const;
|
||||
uint num_committed_nvdimm() const;
|
||||
|
||||
// Similar to find_unavailable_from_idx() function from base class, difference is this function searches in range [start, end].
|
||||
uint find_unavailable_in_range(uint start_idx, uint end_idx, uint* res_idx) const;
|
||||
|
||||
// Expand into dram. Maintains the invariant that total number of committed regions is less than current heap size.
|
||||
uint expand_dram(uint num_regions, WorkGang* pretouch_workers);
|
||||
|
||||
// Expand into nv-dimm.
|
||||
uint expand_nvdimm(uint num_regions, WorkGang* pretouch_workers);
|
||||
|
||||
// Expand by finding unavailable regions in [start, end] range.
|
||||
uint expand_in_range(uint start, uint end, uint num_regions, WorkGang* pretouch_workers);
|
||||
|
||||
// Shrink dram set of regions.
|
||||
uint shrink_dram(uint num_regions, bool update_free_list = true);
|
||||
|
||||
// Shrink nv-dimm set of regions.
|
||||
uint shrink_nvdimm(uint num_regions, bool update_free_list = true);
|
||||
|
||||
// Shrink regions from [start, end] range.
|
||||
uint shrink_in_range(uint start, uint end, uint num_regions, bool update_free_list = true);
|
||||
|
||||
// Similar to find_empty_from_idx_reverse() in base class. Only here it searches in a range.
|
||||
uint find_empty_in_range_reverse(uint start_idx, uint end_idx, uint* res_idx);
|
||||
|
||||
// Similar to find_contiguous() in base class, with [start, end] range
|
||||
uint find_contiguous(size_t start, size_t end, size_t num, bool empty_only);
|
||||
|
||||
// This function is called when there are no free nv-dimm regions.
|
||||
// It borrows a region from the set of unavailable regions in nv-dimm for GC purpose.
|
||||
HeapRegion* borrow_old_region_for_gc();
|
||||
|
||||
uint free_list_dram_length() const;
|
||||
uint free_list_nvdimm_length() const;
|
||||
|
||||
// is region with given index in nv-dimm?
|
||||
bool is_in_nvdimm(uint index) const;
|
||||
bool is_in_dram(uint index) const;
|
||||
|
||||
public:
|
||||
|
||||
// Empty constructor, we'll initialize it with the initialize() method.
|
||||
HeterogeneousHeapRegionManager(uint num_regions) : _max_regions(num_regions), _max_dram_regions(0),
|
||||
_max_nvdimm_regions(0), _start_index_of_nvdimm(0),
|
||||
_total_commited_before_full_gc(0), _no_borrowed_regions(0)
|
||||
{}
|
||||
|
||||
static HeterogeneousHeapRegionManager* manager();
|
||||
|
||||
virtual void initialize(G1RegionToSpaceMapper* heap_storage,
|
||||
G1RegionToSpaceMapper* prev_bitmap,
|
||||
G1RegionToSpaceMapper* next_bitmap,
|
||||
G1RegionToSpaceMapper* bot,
|
||||
G1RegionToSpaceMapper* cardtable,
|
||||
G1RegionToSpaceMapper* card_counts);
|
||||
|
||||
uint start_index_of_nvdimm() const;
|
||||
uint start_index_of_dram() const;
|
||||
uint end_index_of_nvdimm() const;
|
||||
uint end_index_of_dram() const;
|
||||
|
||||
// Override.
|
||||
HeapRegion* get_dummy_region();
|
||||
|
||||
// Adjust dram_set to provision 'expected_num_regions' regions.
|
||||
void adjust_dram_regions(uint expected_num_regions, WorkGang* pretouch_workers);
|
||||
|
||||
// Prepare heap regions before and after full collection.
|
||||
void prepare_for_full_collection_start();
|
||||
void prepare_for_full_collection_end();
|
||||
|
||||
virtual HeapRegion* allocate_free_region(HeapRegionType type, uint node_index);
|
||||
virtual HeapRegion* allocate_humongous_from_free_list(uint num_regions);
|
||||
virtual HeapRegion* allocate_humongous_allow_expand(uint num_regions);
|
||||
|
||||
// Return maximum number of regions that heap can expand to.
|
||||
uint max_length() const;
|
||||
|
||||
// Override. Expand in nv-dimm.
|
||||
uint expand_by(uint num_regions, WorkGang* pretouch_workers);
|
||||
|
||||
// Override.
|
||||
uint expand_at(uint start, uint num_regions, WorkGang* pretouch_workers);
|
||||
|
||||
// Overrides base class implementation to find highest free region in dram.
|
||||
uint find_highest_free(bool* expanded);
|
||||
|
||||
// Override. This fuction is called to shrink the heap, we shrink in dram first then in nv-dimm.
|
||||
uint shrink_by(uint num_regions_to_remove);
|
||||
|
||||
bool has_borrowed_regions() const;
|
||||
|
||||
void verify();
|
||||
};
|
||||
|
||||
#endif // SHARE_GC_G1_HETEROGENEOUSHEAPREGIONMANAGER_HPP
|
@ -55,7 +55,7 @@
|
||||
nonstatic_field(HeapRegionManager, _regions, G1HeapRegionTable) \
|
||||
\
|
||||
volatile_nonstatic_field(G1CollectedHeap, _summary_bytes_used, size_t) \
|
||||
nonstatic_field(G1CollectedHeap, _hrm, HeapRegionManager*) \
|
||||
nonstatic_field(G1CollectedHeap, _hrm, HeapRegionManager) \
|
||||
nonstatic_field(G1CollectedHeap, _g1mm, G1MonitoringSupport*) \
|
||||
nonstatic_field(G1CollectedHeap, _old_set, HeapRegionSetBase) \
|
||||
nonstatic_field(G1CollectedHeap, _archive_set, HeapRegionSetBase) \
|
||||
|
@ -37,8 +37,6 @@
|
||||
#include "utilities/defaultStream.hpp"
|
||||
#include "utilities/powerOfTwo.hpp"
|
||||
|
||||
static const double MaxRamFractionForYoung = 0.8;
|
||||
|
||||
size_t ParallelArguments::conservative_max_heap_alignment() {
|
||||
return compute_heap_alignment();
|
||||
}
|
||||
@ -116,10 +114,6 @@ void ParallelArguments::initialize_heap_flags_and_sizes_one_pass() {
|
||||
}
|
||||
|
||||
void ParallelArguments::initialize_heap_flags_and_sizes() {
|
||||
if (is_heterogeneous_heap()) {
|
||||
initialize_heterogeneous();
|
||||
}
|
||||
|
||||
initialize_heap_flags_and_sizes_one_pass();
|
||||
|
||||
const size_t min_pages = 4; // 1 for eden + 1 for each survivor + 1 for old
|
||||
@ -136,61 +130,6 @@ void ParallelArguments::initialize_heap_flags_and_sizes() {
|
||||
}
|
||||
}
|
||||
|
||||
// Check the available dram memory to limit NewSize and MaxNewSize before
|
||||
// calling base class initialize_flags().
|
||||
void ParallelArguments::initialize_heterogeneous() {
|
||||
FormatBuffer<100> calc_str("");
|
||||
|
||||
julong phys_mem;
|
||||
// If MaxRam is specified, we use that as maximum physical memory available.
|
||||
if (FLAG_IS_DEFAULT(MaxRAM)) {
|
||||
phys_mem = os::physical_memory();
|
||||
calc_str.append("Physical_Memory");
|
||||
} else {
|
||||
phys_mem = (julong)MaxRAM;
|
||||
calc_str.append("MaxRAM");
|
||||
}
|
||||
|
||||
julong reasonable_max = phys_mem;
|
||||
|
||||
// If either MaxRAMFraction or MaxRAMPercentage is specified, we use them to calculate
|
||||
// reasonable max size of young generation.
|
||||
if (!FLAG_IS_DEFAULT(MaxRAMFraction)) {
|
||||
reasonable_max = (julong)(phys_mem / MaxRAMFraction);
|
||||
calc_str.append(" / MaxRAMFraction");
|
||||
} else if (!FLAG_IS_DEFAULT(MaxRAMPercentage)) {
|
||||
reasonable_max = (julong)((phys_mem * MaxRAMPercentage) / 100);
|
||||
calc_str.append(" * MaxRAMPercentage / 100");
|
||||
} else {
|
||||
// We use our own fraction to calculate max size of young generation.
|
||||
reasonable_max = phys_mem * MaxRamFractionForYoung;
|
||||
calc_str.append(" * %0.2f", MaxRamFractionForYoung);
|
||||
}
|
||||
reasonable_max = align_up(reasonable_max, GenAlignment);
|
||||
|
||||
if (MaxNewSize > reasonable_max) {
|
||||
if (FLAG_IS_CMDLINE(MaxNewSize)) {
|
||||
log_warning(gc, ergo)("Setting MaxNewSize to " SIZE_FORMAT " based on dram available (calculation = align(%s))",
|
||||
(size_t)reasonable_max, calc_str.buffer());
|
||||
} else {
|
||||
log_info(gc, ergo)("Setting MaxNewSize to " SIZE_FORMAT " based on dram available (calculation = align(%s)). "
|
||||
"Dram usage can be lowered by setting MaxNewSize to a lower value", (size_t)reasonable_max, calc_str.buffer());
|
||||
}
|
||||
MaxNewSize = reasonable_max;
|
||||
}
|
||||
if (NewSize > reasonable_max) {
|
||||
if (FLAG_IS_CMDLINE(NewSize)) {
|
||||
log_warning(gc, ergo)("Setting NewSize to " SIZE_FORMAT " based on dram available (calculation = align(%s))",
|
||||
(size_t)reasonable_max, calc_str.buffer());
|
||||
}
|
||||
NewSize = reasonable_max;
|
||||
}
|
||||
}
|
||||
|
||||
bool ParallelArguments::is_heterogeneous_heap() {
|
||||
return AllocateOldGenAt != NULL;
|
||||
}
|
||||
|
||||
size_t ParallelArguments::heap_reserved_size_bytes() {
|
||||
return MaxHeapSize;
|
||||
}
|
||||
|
@ -36,15 +36,12 @@ private:
|
||||
virtual void initialize_heap_flags_and_sizes();
|
||||
|
||||
void initialize_heap_flags_and_sizes_one_pass();
|
||||
void initialize_heterogeneous();
|
||||
|
||||
virtual void initialize();
|
||||
virtual size_t conservative_max_heap_alignment();
|
||||
virtual CollectedHeap* create_heap();
|
||||
|
||||
public:
|
||||
// Heterogeneous heap support
|
||||
static bool is_heterogeneous_heap();
|
||||
static size_t heap_reserved_size_bytes();
|
||||
static size_t heap_max_size_bytes();
|
||||
};
|
||||
|
@ -83,8 +83,7 @@ jint ParallelScavengeHeap::initialize() {
|
||||
assert(MinNewSize <= NewSize && NewSize <= MaxNewSize, "Parameter check");
|
||||
|
||||
// Layout the reserved space for the generations.
|
||||
// If OldGen is allocated on nv-dimm, we need to split the reservation (this is required for windows).
|
||||
ReservedSpace old_rs = heap_rs.first_part(MaxOldSize, ParallelArguments::is_heterogeneous_heap() /* split */);
|
||||
ReservedSpace old_rs = heap_rs.first_part(MaxOldSize);
|
||||
ReservedSpace young_rs = heap_rs.last_part(MaxOldSize);
|
||||
assert(young_rs.size() == MaxNewSize, "Didn't reserve all of the heap");
|
||||
|
||||
@ -123,8 +122,7 @@ jint ParallelScavengeHeap::initialize() {
|
||||
GCTimeRatio
|
||||
);
|
||||
|
||||
assert(ParallelArguments::is_heterogeneous_heap() ||
|
||||
(old_gen()->virtual_space()->high_boundary() ==
|
||||
assert((old_gen()->virtual_space()->high_boundary() ==
|
||||
young_gen()->virtual_space()->low_boundary()),
|
||||
"Boundaries must meet");
|
||||
// initialize the policy counters - 2 collectors, 2 generations
|
||||
|
@ -1,83 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "precompiled.hpp"
|
||||
#include "gc/parallel/psFileBackedVirtualspace.hpp"
|
||||
#include "memory/virtualspace.hpp"
|
||||
#include "runtime/os.inline.hpp"
|
||||
|
||||
PSFileBackedVirtualSpace::PSFileBackedVirtualSpace(ReservedSpace rs, size_t alignment, const char* path) : PSVirtualSpace(rs, alignment),
|
||||
_file_path(path), _fd(-1), _mapping_succeeded(false) {
|
||||
assert(!rs.special(), "ReservedSpace passed to PSFileBackedVirtualSpace cannot be special");
|
||||
}
|
||||
|
||||
bool PSFileBackedVirtualSpace::initialize() {
|
||||
_fd = os::create_file_for_heap(_file_path);
|
||||
if (_fd == -1) {
|
||||
return false;
|
||||
}
|
||||
// We map the reserved space to a file at initialization.
|
||||
char* ret = os::replace_existing_mapping_with_file_mapping(reserved_low_addr(), reserved_size(), _fd);
|
||||
if (ret != reserved_low_addr()) {
|
||||
os::close(_fd);
|
||||
return false;
|
||||
}
|
||||
// _mapping_succeeded is false if we return before this point.
|
||||
// expand calls later check value of this flag and return error if it is false.
|
||||
_mapping_succeeded = true;
|
||||
_special = true;
|
||||
os::close(_fd);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PSFileBackedVirtualSpace::expand_by(size_t bytes) {
|
||||
assert(special(), "Since entire space is committed at initialization, _special should always be true for PSFileBackedVirtualSpace");
|
||||
|
||||
// if mapping did not succeed during intialization return false
|
||||
if (!_mapping_succeeded) {
|
||||
return false;
|
||||
}
|
||||
return PSVirtualSpace::expand_by(bytes);
|
||||
|
||||
}
|
||||
|
||||
bool PSFileBackedVirtualSpace::shrink_by(size_t bytes) {
|
||||
assert(special(), "Since entire space is committed at initialization, _special should always be true for PSFileBackedVirtualSpace");
|
||||
return PSVirtualSpace::shrink_by(bytes);
|
||||
}
|
||||
|
||||
size_t PSFileBackedVirtualSpace::expand_into(PSVirtualSpace* space, size_t bytes) {
|
||||
// not supported. Since doing this will change page mapping which will lead to large TLB penalties.
|
||||
assert(false, "expand_into() should not be called for PSFileBackedVirtualSpace");
|
||||
return 0;
|
||||
}
|
||||
|
||||
void PSFileBackedVirtualSpace::release() {
|
||||
os::close(_fd);
|
||||
_fd = -1;
|
||||
_file_path = NULL;
|
||||
|
||||
PSVirtualSpace::release();
|
||||
}
|
||||
|
@ -1,44 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SHARE_GC_PARALLEL_PSFILEBACKEDVIRTUALSPACE_HPP
|
||||
#define SHARE_GC_PARALLEL_PSFILEBACKEDVIRTUALSPACE_HPP
|
||||
|
||||
#include "gc/parallel/psVirtualspace.hpp"
|
||||
|
||||
class PSFileBackedVirtualSpace : public PSVirtualSpace {
|
||||
private:
|
||||
const char* _file_path;
|
||||
int _fd;
|
||||
bool _mapping_succeeded;
|
||||
public:
|
||||
PSFileBackedVirtualSpace(ReservedSpace rs, size_t alignment, const char* file_path);
|
||||
|
||||
bool initialize();
|
||||
bool expand_by(size_t bytes);
|
||||
bool shrink_by(size_t bytes);
|
||||
size_t expand_into(PSVirtualSpace* space, size_t bytes);
|
||||
void release();
|
||||
};
|
||||
#endif // SHARE_GC_PARALLEL_PSFILEBACKEDVIRTUALSPACE_HPP
|
@ -28,7 +28,6 @@
|
||||
#include "gc/parallel/parallelScavengeHeap.hpp"
|
||||
#include "gc/parallel/psAdaptiveSizePolicy.hpp"
|
||||
#include "gc/parallel/psCardTable.hpp"
|
||||
#include "gc/parallel/psFileBackedVirtualspace.hpp"
|
||||
#include "gc/parallel/psOldGen.hpp"
|
||||
#include "gc/shared/cardTableBarrierSet.hpp"
|
||||
#include "gc/shared/gcLocker.hpp"
|
||||
@ -62,14 +61,7 @@ void PSOldGen::initialize_virtual_space(ReservedSpace rs,
|
||||
size_t initial_size,
|
||||
size_t alignment) {
|
||||
|
||||
if(ParallelArguments::is_heterogeneous_heap()) {
|
||||
_virtual_space = new PSFileBackedVirtualSpace(rs, alignment, AllocateOldGenAt);
|
||||
if (!(static_cast <PSFileBackedVirtualSpace*>(_virtual_space))->initialize()) {
|
||||
vm_exit_during_initialization("Could not map space for PSOldGen at given AllocateOldGenAt path");
|
||||
}
|
||||
} else {
|
||||
_virtual_space = new PSVirtualSpace(rs, alignment);
|
||||
}
|
||||
_virtual_space = new PSVirtualSpace(rs, alignment);
|
||||
if (!_virtual_space->expand_by(initial_size)) {
|
||||
vm_exit_during_initialization("Could not reserve enough space for "
|
||||
"object heap");
|
||||
|
@ -30,7 +30,6 @@
|
||||
#include "runtime/arguments.hpp"
|
||||
#include "runtime/globals.hpp"
|
||||
#include "runtime/globals_extension.hpp"
|
||||
#include "utilities/defaultStream.hpp"
|
||||
#include "utilities/macros.hpp"
|
||||
|
||||
size_t HeapAlignment = 0;
|
||||
@ -59,15 +58,6 @@ void GCArguments::initialize() {
|
||||
// If class unloading is disabled, also disable concurrent class unloading.
|
||||
FLAG_SET_CMDLINE(ClassUnloadingWithConcurrentMark, false);
|
||||
}
|
||||
|
||||
if (!FLAG_IS_DEFAULT(AllocateOldGenAt)) {
|
||||
// CompressedOops not supported when AllocateOldGenAt is set.
|
||||
LP64_ONLY(FLAG_SET_DEFAULT(UseCompressedOops, false));
|
||||
LP64_ONLY(FLAG_SET_DEFAULT(UseCompressedClassPointers, false));
|
||||
// When AllocateOldGenAt is set, we cannot use largepages for entire heap memory.
|
||||
// Only young gen which is allocated in dram can use large pages, but we currently don't support that.
|
||||
FLAG_SET_DEFAULT(UseLargePages, false);
|
||||
}
|
||||
}
|
||||
|
||||
void GCArguments::initialize_heap_sizes() {
|
||||
@ -94,21 +84,6 @@ size_t GCArguments::compute_heap_alignment() {
|
||||
return alignment;
|
||||
}
|
||||
|
||||
bool GCArguments::check_args_consistency() {
|
||||
bool status = true;
|
||||
if (!FLAG_IS_DEFAULT(AllocateHeapAt) && !FLAG_IS_DEFAULT(AllocateOldGenAt)) {
|
||||
jio_fprintf(defaultStream::error_stream(),
|
||||
"AllocateHeapAt and AllocateOldGenAt cannot be used together.\n");
|
||||
status = false;
|
||||
}
|
||||
if (!FLAG_IS_DEFAULT(AllocateOldGenAt) && (UseSerialGC || UseEpsilonGC || UseZGC)) {
|
||||
jio_fprintf(defaultStream::error_stream(),
|
||||
"AllocateOldGenAt is not supported for selected GC.\n");
|
||||
status = false;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
#ifdef ASSERT
|
||||
void GCArguments::assert_flags() {
|
||||
assert(InitialHeapSize <= MaxHeapSize, "Ergonomics decided on incompatible initial and maximum heap sizes");
|
||||
|
@ -56,8 +56,6 @@ public:
|
||||
void initialize_heap_sizes();
|
||||
|
||||
static size_t compute_heap_alignment();
|
||||
|
||||
static bool check_args_consistency();
|
||||
};
|
||||
|
||||
#endif // SHARE_GC_SHARED_GCARGUMENTS_HPP
|
||||
|
@ -97,7 +97,6 @@
|
||||
#include "gc/g1/g1ConcurrentMark.hpp"
|
||||
#include "gc/g1/g1ConcurrentMarkThread.inline.hpp"
|
||||
#include "gc/g1/heapRegionRemSet.hpp"
|
||||
#include "gc/g1/heterogeneousHeapRegionManager.hpp"
|
||||
#endif // INCLUDE_G1GC
|
||||
#if INCLUDE_PARALLELGC
|
||||
#include "gc/parallel/parallelScavengeHeap.inline.hpp"
|
||||
@ -507,115 +506,6 @@ WB_END
|
||||
|
||||
#endif // INCLUDE_G1GC
|
||||
|
||||
#if INCLUDE_G1GC || INCLUDE_PARALLELGC
|
||||
WB_ENTRY(jlong, WB_DramReservedStart(JNIEnv* env, jobject o))
|
||||
#if INCLUDE_G1GC
|
||||
if (UseG1GC) {
|
||||
G1CollectedHeap* g1h = G1CollectedHeap::heap();
|
||||
HeapWord* base = g1h->reserved().start();
|
||||
if (g1h->is_heterogeneous_heap()) {
|
||||
uint start_region = HeterogeneousHeapRegionManager::manager()->start_index_of_dram();
|
||||
return (jlong)(base + start_region * HeapRegion::GrainBytes);
|
||||
} else {
|
||||
return (jlong)base;
|
||||
}
|
||||
}
|
||||
#endif // INCLUDE_G1GC
|
||||
#if INCLUDE_PARALLELGC
|
||||
if (UseParallelGC) {
|
||||
ParallelScavengeHeap* ps_heap = ParallelScavengeHeap::heap();
|
||||
if (AllocateOldGenAt != NULL) {
|
||||
MemRegion reserved = ps_heap->young_gen()->reserved();
|
||||
return (jlong)reserved.start();
|
||||
} else {
|
||||
return (jlong)ps_heap->base();
|
||||
}
|
||||
}
|
||||
#endif // INCLUDE_PARALLELGC
|
||||
THROW_MSG_0(vmSymbols::java_lang_UnsupportedOperationException(), "WB_DramReservedStart: enabled only for G1 and Parallel GC");
|
||||
WB_END
|
||||
|
||||
WB_ENTRY(jlong, WB_DramReservedEnd(JNIEnv* env, jobject o))
|
||||
#if INCLUDE_G1GC
|
||||
if (UseG1GC) {
|
||||
G1CollectedHeap* g1h = G1CollectedHeap::heap();
|
||||
HeapWord* base = g1h->reserved().start();
|
||||
if (g1h->is_heterogeneous_heap()) {
|
||||
uint end_region = HeterogeneousHeapRegionManager::manager()->end_index_of_dram();
|
||||
return (jlong)(base + (end_region + 1) * HeapRegion::GrainBytes - 1);
|
||||
} else {
|
||||
return (jlong)base + G1Arguments::heap_max_size_bytes();
|
||||
}
|
||||
}
|
||||
#endif // INCLUDE_G1GC
|
||||
#if INCLUDE_PARALLELGC
|
||||
if (UseParallelGC) {
|
||||
ParallelScavengeHeap* ps_heap = ParallelScavengeHeap::heap();
|
||||
if (AllocateOldGenAt != NULL) {
|
||||
MemRegion reserved = ps_heap->young_gen()->reserved();
|
||||
return (jlong)reserved.end();
|
||||
} else {
|
||||
return (jlong)ps_heap->reserved_region().end();
|
||||
}
|
||||
}
|
||||
#endif // INCLUDE_PARALLELGC
|
||||
THROW_MSG_0(vmSymbols::java_lang_UnsupportedOperationException(), "WB_DramReservedEnd: enabled only for G1 and Parallel GC");
|
||||
WB_END
|
||||
|
||||
WB_ENTRY(jlong, WB_NvdimmReservedStart(JNIEnv* env, jobject o))
|
||||
#if INCLUDE_G1GC
|
||||
if (UseG1GC) {
|
||||
G1CollectedHeap* g1h = G1CollectedHeap::heap();
|
||||
if (g1h->is_heterogeneous_heap()) {
|
||||
uint start_region = HeterogeneousHeapRegionManager::manager()->start_index_of_nvdimm();
|
||||
return (jlong)(g1h->reserved().start() + start_region * HeapRegion::GrainBytes);
|
||||
} else {
|
||||
THROW_MSG_0(vmSymbols::java_lang_UnsupportedOperationException(), "WB_NvdimmReservedStart: Old gen is not allocated on NV-DIMM using AllocateOldGenAt flag");
|
||||
}
|
||||
}
|
||||
#endif // INCLUDE_G1GC
|
||||
#if INCLUDE_PARALLELGC
|
||||
if (UseParallelGC) {
|
||||
ParallelScavengeHeap* ps_heap = ParallelScavengeHeap::heap();
|
||||
if (AllocateOldGenAt != NULL) {
|
||||
MemRegion reserved = ps_heap->old_gen()->reserved();
|
||||
return (jlong)reserved.start();
|
||||
} else {
|
||||
THROW_MSG_0(vmSymbols::java_lang_UnsupportedOperationException(), "WB_NvdimmReservedStart: Old gen is not allocated on NV-DIMM using AllocateOldGenAt flag");
|
||||
}
|
||||
}
|
||||
#endif // INCLUDE_PARALLELGC
|
||||
THROW_MSG_0(vmSymbols::java_lang_UnsupportedOperationException(), "WB_NvdimmReservedStart: enabled only for G1 and Parallel GC");
|
||||
WB_END
|
||||
|
||||
WB_ENTRY(jlong, WB_NvdimmReservedEnd(JNIEnv* env, jobject o))
|
||||
#if INCLUDE_G1GC
|
||||
if (UseG1GC) {
|
||||
G1CollectedHeap* g1h = G1CollectedHeap::heap();
|
||||
if (g1h->is_heterogeneous_heap()) {
|
||||
uint end_region = HeterogeneousHeapRegionManager::manager()->start_index_of_nvdimm();
|
||||
return (jlong)(g1h->reserved().start() + (end_region + 1) * HeapRegion::GrainBytes - 1);
|
||||
} else {
|
||||
THROW_MSG_0(vmSymbols::java_lang_UnsupportedOperationException(), "WB_NvdimmReservedEnd: Old gen is not allocated on NV-DIMM using AllocateOldGenAt flag");
|
||||
}
|
||||
}
|
||||
#endif // INCLUDE_G1GC
|
||||
#if INCLUDE_PARALLELGC
|
||||
if (UseParallelGC) {
|
||||
ParallelScavengeHeap* ps_heap = ParallelScavengeHeap::heap();
|
||||
if (AllocateOldGenAt != NULL) {
|
||||
MemRegion reserved = ps_heap->old_gen()->reserved();
|
||||
return (jlong)reserved.end();
|
||||
} else {
|
||||
THROW_MSG_0(vmSymbols::java_lang_UnsupportedOperationException(), "WB_NvdimmReservedEnd: Old gen is not allocated on NV-DIMM using AllocateOldGenAt flag");
|
||||
}
|
||||
}
|
||||
#endif // INCLUDE_PARALLELGC
|
||||
THROW_MSG_0(vmSymbols::java_lang_UnsupportedOperationException(), "WB_NvdimmReservedEnd: enabled only for G1 and Parallel GC");
|
||||
WB_END
|
||||
|
||||
#endif // INCLUDE_G1GC || INCLUDE_PARALLELGC
|
||||
|
||||
#if INCLUDE_PARALLELGC
|
||||
|
||||
WB_ENTRY(jlong, WB_PSVirtualSpaceAlignment(JNIEnv* env, jobject o))
|
||||
@ -2418,12 +2308,6 @@ static JNINativeMethod methods[] = {
|
||||
{CC"g1MemoryNodeIds", CC"()[I", (void*)&WB_G1MemoryNodeIds },
|
||||
{CC"g1GetMixedGCInfo", CC"(I)[J", (void*)&WB_G1GetMixedGCInfo },
|
||||
#endif // INCLUDE_G1GC
|
||||
#if INCLUDE_G1GC || INCLUDE_PARALLELGC
|
||||
{CC"dramReservedStart", CC"()J", (void*)&WB_DramReservedStart },
|
||||
{CC"dramReservedEnd", CC"()J", (void*)&WB_DramReservedEnd },
|
||||
{CC"nvdimmReservedStart", CC"()J", (void*)&WB_NvdimmReservedStart },
|
||||
{CC"nvdimmReservedEnd", CC"()J", (void*)&WB_NvdimmReservedEnd },
|
||||
#endif // INCLUDE_G1GC || INCLUDE_PARALLELGC
|
||||
#if INCLUDE_PARALLELGC
|
||||
{CC"psVirtualSpaceAlignment",CC"()J", (void*)&WB_PSVirtualSpaceAlignment},
|
||||
{CC"psHeapGenerationAlignment",CC"()J", (void*)&WB_PSHeapGenerationAlignment},
|
||||
|
@ -2161,8 +2161,6 @@ bool Arguments::check_vm_args_consistency() {
|
||||
}
|
||||
#endif
|
||||
|
||||
status = status && GCArguments::check_args_consistency();
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
@ -4080,7 +4078,6 @@ jint Arguments::parse(const JavaVMInitArgs* initial_cmd_args) {
|
||||
|
||||
#if defined(AIX)
|
||||
UNSUPPORTED_OPTION_NULL(AllocateHeapAt);
|
||||
UNSUPPORTED_OPTION_NULL(AllocateOldGenAt);
|
||||
#endif
|
||||
|
||||
#ifndef PRODUCT
|
||||
|
@ -2470,12 +2470,6 @@ const intx ObjectAlignmentInBytes = 8;
|
||||
"Path to the directoy where a temporary file will be created " \
|
||||
"to use as the backing store for Java Heap.") \
|
||||
\
|
||||
product(ccstr, AllocateOldGenAt, NULL, EXPERIMENTAL, \
|
||||
"Path to the directoy where a temporary file will be " \
|
||||
"created to use as the backing store for old generation." \
|
||||
"File of size Xmx is pre-allocated for performance reason, so" \
|
||||
"we need that much space available") \
|
||||
\
|
||||
develop(int, VerifyMetaspaceInterval, DEBUG_ONLY(500) NOT_DEBUG(0), \
|
||||
"Run periodic metaspace verifications (0 - none, " \
|
||||
"1 - always, >1 every nth interval)") \
|
||||
|
@ -48,7 +48,7 @@ import sun.jvm.hotspot.tools.HeapSummary;
|
||||
|
||||
public class G1CollectedHeap extends CollectedHeap {
|
||||
// HeapRegionManager _hrm;
|
||||
static private AddressField hrmField;
|
||||
static private long hrmFieldOffset;
|
||||
// MemRegion _g1_reserved;
|
||||
static private long g1ReservedFieldOffset;
|
||||
// size_t _summary_bytes_used;
|
||||
@ -73,7 +73,7 @@ public class G1CollectedHeap extends CollectedHeap {
|
||||
static private synchronized void initialize(TypeDataBase db) {
|
||||
Type type = db.lookupType("G1CollectedHeap");
|
||||
|
||||
hrmField = type.getAddressField("_hrm");
|
||||
hrmFieldOffset = type.getField("_hrm").getOffset();
|
||||
summaryBytesUsedField = type.getCIntegerField("_summary_bytes_used");
|
||||
g1mmField = type.getAddressField("_g1mm");
|
||||
oldSetFieldOffset = type.getField("_old_set").getOffset();
|
||||
@ -94,9 +94,9 @@ public class G1CollectedHeap extends CollectedHeap {
|
||||
}
|
||||
|
||||
public HeapRegionManager hrm() {
|
||||
Address hrmAddr = hrmField.getValue(addr);
|
||||
Address hrmAddr = addr.addOffsetTo(hrmFieldOffset);
|
||||
return (HeapRegionManager) VMObjectFactory.newObject(HeapRegionManager.class,
|
||||
hrmAddr);
|
||||
hrmAddr);
|
||||
}
|
||||
|
||||
public G1MonitoringSupport g1mm() {
|
||||
|
@ -76,7 +76,6 @@ requires.properties= \
|
||||
vm.compiler2.enabled \
|
||||
vm.musl \
|
||||
docker.support \
|
||||
test.vm.gc.nvdimm \
|
||||
jdk.containerized
|
||||
|
||||
# Minimum jtreg version
|
||||
|
@ -42,8 +42,7 @@ hotspot_compiler_all_gcs = \
|
||||
-compiler/graalunit
|
||||
|
||||
hotspot_gc = \
|
||||
gc \
|
||||
-gc/nvdimm
|
||||
gc
|
||||
|
||||
# By design this group should include ALL tests under runtime sub-directory
|
||||
hotspot_runtime = \
|
||||
@ -66,7 +65,6 @@ hotspot_misc = \
|
||||
-:hotspot_gc \
|
||||
-:hotspot_runtime \
|
||||
-:hotspot_serviceability \
|
||||
-gc/nvdimm \
|
||||
-:hotspot_containers
|
||||
|
||||
hotspot_native_sanity = \
|
||||
@ -203,8 +201,7 @@ tier1_gc_2 = \
|
||||
-gc/logging/TestUnifiedLoggingSwitchStress.java \
|
||||
-gc/stress \
|
||||
-gc/metaspace/CompressedClassSpaceSizeInJmapHeap.java \
|
||||
-gc/shenandoah \
|
||||
-gc/nvdimm
|
||||
-gc/shenandoah
|
||||
|
||||
gc_epsilon = \
|
||||
gc/epsilon/ \
|
||||
|
@ -1,67 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package gc.nvdimm;
|
||||
|
||||
/* @test TestAllocateOldGenAt.java
|
||||
* @summary Test to check allocation of Java Heap with AllocateOldGenAt option
|
||||
* @requires vm.gc=="null" & os.family != "aix"
|
||||
* @requires test.vm.gc.nvdimm
|
||||
* @library /test/lib
|
||||
* @modules java.base/jdk.internal.misc
|
||||
* @run driver gc.nvdimm.TestAllocateOldGenAt
|
||||
*/
|
||||
|
||||
import jdk.test.lib.JDKToolFinder;
|
||||
import jdk.test.lib.process.ProcessTools;
|
||||
import jdk.test.lib.process.OutputAnalyzer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
|
||||
public class TestAllocateOldGenAt {
|
||||
private static String[] commonFlags;
|
||||
|
||||
public static void main(String args[]) throws Exception {
|
||||
String test_dir = System.getProperty("test.dir", ".");
|
||||
commonFlags = new String[] {
|
||||
"-XX:+UnlockExperimentalVMOptions",
|
||||
"-XX:AllocateOldGenAt=" + test_dir,
|
||||
"-Xmx32m",
|
||||
"-Xms32m",
|
||||
"-version"};
|
||||
|
||||
runTest("-XX:+UseG1GC");
|
||||
runTest("-XX:+UseParallelGC");
|
||||
}
|
||||
|
||||
private static void runTest(String... extraFlags) throws Exception {
|
||||
ArrayList<String> flags = new ArrayList<>();
|
||||
Collections.addAll(flags, commonFlags);
|
||||
Collections.addAll(flags, extraFlags);
|
||||
ProcessBuilder pb = ProcessTools.createTestJvm(flags);
|
||||
OutputAnalyzer output = new OutputAnalyzer(pb.start());
|
||||
|
||||
output.shouldHaveExitValue(0);
|
||||
|
||||
}
|
||||
}
|
@ -1,95 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package gc.nvdimm;
|
||||
|
||||
/* @test TestAllocateOldGenAtError.java
|
||||
* @summary Test to check correct handling of non-existent directory passed to AllocateOldGenAt option
|
||||
* @requires vm.gc=="null" & os.family != "aix"
|
||||
* @requires test.vm.gc.nvdimm
|
||||
* @library /test/lib
|
||||
* @modules java.base/jdk.internal.misc
|
||||
* @run driver gc.nvdimm.TestAllocateOldGenAtError
|
||||
*/
|
||||
|
||||
import java.io.File;
|
||||
import jdk.test.lib.JDKToolFinder;
|
||||
import jdk.test.lib.process.ProcessTools;
|
||||
import jdk.test.lib.process.OutputAnalyzer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.UUID;
|
||||
|
||||
public class TestAllocateOldGenAtError {
|
||||
private static String[] commonFlags;
|
||||
|
||||
public static void main(String args[]) throws Exception {
|
||||
String test_dir = System.getProperty("test.dir", ".");
|
||||
|
||||
File f = null;
|
||||
do {
|
||||
f = new File(test_dir, UUID.randomUUID().toString());
|
||||
} while(f.exists());
|
||||
|
||||
commonFlags = new String[] {
|
||||
"-XX:+UnlockExperimentalVMOptions",
|
||||
"-XX:AllocateOldGenAt=" + f.getName(),
|
||||
"-Xlog:gc+heap=info",
|
||||
"-Xmx32m",
|
||||
"-Xms32m",
|
||||
"-version"};
|
||||
|
||||
testG1();
|
||||
testParallelOld();
|
||||
}
|
||||
|
||||
private static void testG1() throws Exception {
|
||||
System.out.println("Testing G1 GC");
|
||||
|
||||
OutputAnalyzer output = runTest("-XX:+UseG1GC");
|
||||
|
||||
output.shouldContain("Could not initialize G1 heap");
|
||||
output.shouldContain("Error occurred during initialization of VM");
|
||||
output.shouldNotHaveExitValue(0);
|
||||
|
||||
}
|
||||
|
||||
private static void testParallelOld() throws Exception {
|
||||
System.out.println("Testing Parallel GC");
|
||||
|
||||
OutputAnalyzer output = runTest("-XX:+UseParallelGC");
|
||||
|
||||
output.shouldContain("Error occurred during initialization of VM");
|
||||
output.shouldNotHaveExitValue(0);
|
||||
}
|
||||
|
||||
private static OutputAnalyzer runTest(String... extraFlags) throws Exception {
|
||||
ArrayList<String> flags = new ArrayList<>();
|
||||
Collections.addAll(flags, commonFlags);
|
||||
Collections.addAll(flags, extraFlags);
|
||||
|
||||
ProcessBuilder pb = ProcessTools.createTestJvm(flags);
|
||||
OutputAnalyzer output = new OutputAnalyzer(pb.start());
|
||||
return output;
|
||||
}
|
||||
}
|
@ -1,73 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package gc.nvdimm;
|
||||
|
||||
/* @test TestAllocateOldGenAtMultiple.java
|
||||
* @summary Test to check allocation of Java Heap with AllocateOldGenAt option. Has multiple sub-tests to cover different code paths.
|
||||
* @requires vm.gc=="null" & os.family != "aix"
|
||||
* @requires test.vm.gc.nvdimm
|
||||
* @library /test/lib
|
||||
* @modules java.base/jdk.internal.misc
|
||||
* @requires vm.bits == "64"
|
||||
* @run driver gc.nvdimm.TestAllocateOldGenAtMultiple
|
||||
*/
|
||||
|
||||
import jdk.test.lib.JDKToolFinder;
|
||||
import jdk.test.lib.process.ProcessTools;
|
||||
import jdk.test.lib.process.OutputAnalyzer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
|
||||
public class TestAllocateOldGenAtMultiple {
|
||||
public static void main(String args[]) throws Exception {
|
||||
ArrayList<String> flags = new ArrayList<>();
|
||||
String test_dir = System.getProperty("test.dir", ".");
|
||||
|
||||
// Extra flags for each of the sub-tests
|
||||
String[][] extraFlagsList = {
|
||||
{"-Xmx32m", "-Xms32m", "-XX:+UseCompressedOops"}, // 1. With compressedoops enabled.
|
||||
{"-Xmx32m", "-Xms32m", "-XX:-UseCompressedOops"}, // 2. With compressedoops disabled.
|
||||
{"-Xmx32m", "-Xms32m", "-XX:HeapBaseMinAddress=3g"}, // 3. With user specified HeapBaseMinAddress.
|
||||
{"-Xmx4g", "-Xms4g"}, // 4. With larger heap size (UnscaledNarrowOop not possible).
|
||||
{"-Xmx4g", "-Xms4g", "-XX:+UseLargePages"}, // 5. Set UseLargePages.
|
||||
{"-Xmx4g", "-Xms4g", "-XX:+UseNUMA"} // 6. Set UseNUMA.
|
||||
};
|
||||
|
||||
for (String[] extraFlags : extraFlagsList) {
|
||||
flags.clear();
|
||||
// Add extra flags specific to the sub-test.
|
||||
Collections.addAll(flags, extraFlags);
|
||||
// Add common flags
|
||||
Collections.addAll(flags, new String[] {"-XX:+UnlockExperimentalVMOptions",
|
||||
"-XX:AllocateOldGenAt=" + test_dir,
|
||||
"-version"});
|
||||
ProcessBuilder pb = ProcessTools.createTestJvm(flags);
|
||||
OutputAnalyzer output = new OutputAnalyzer(pb.start());
|
||||
|
||||
System.out.println("Output:\n" + output.getOutput());
|
||||
|
||||
output.shouldHaveExitValue(0);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,109 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package gc.nvdimm;
|
||||
|
||||
/*
|
||||
* @test TestHumongousObjectsOnNvdimm
|
||||
* @summary Check that humongous objects reside in nv-dimm
|
||||
* @library /test/lib /
|
||||
* @requires vm.gc=="null" & os.family != "aix"
|
||||
* @requires test.vm.gc.nvdimm
|
||||
* @build sun.hotspot.WhiteBox
|
||||
* @run driver ClassFileInstaller sun.hotspot.WhiteBox
|
||||
* @run driver gc.nvdimm.TestHumongousObjectsOnNvdimm
|
||||
*/
|
||||
|
||||
import jdk.test.lib.process.OutputAnalyzer;
|
||||
import jdk.test.lib.process.ProcessTools;
|
||||
import jdk.test.lib.Asserts;
|
||||
import sun.hotspot.WhiteBox;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import gc.testlibrary.Helpers;
|
||||
|
||||
/**
|
||||
* Test spawns HumongousObjectTest in a separate VM and expects that it
|
||||
* completes without a RuntimeException.
|
||||
*/
|
||||
public class TestHumongousObjectsOnNvdimm {
|
||||
|
||||
private static String[] commonFlags;
|
||||
|
||||
public static void main(String args[]) throws Exception {
|
||||
commonFlags = new String[] {
|
||||
"-Xbootclasspath/a:.",
|
||||
"-XX:+UnlockExperimentalVMOptions",
|
||||
"-XX:+UnlockDiagnosticVMOptions",
|
||||
"-XX:+WhiteBoxAPI",
|
||||
"-XX:AllocateOldGenAt=" + System.getProperty("test.dir", "."),
|
||||
"-Xms10M", "-Xmx10M",
|
||||
"-XX:G1HeapRegionSize=1m"
|
||||
};
|
||||
|
||||
// Test with G1 GC
|
||||
runTest("-XX:+UseG1GC");
|
||||
}
|
||||
|
||||
private static void runTest(String... extraFlags) throws Exception {
|
||||
ArrayList<String> flags = new ArrayList<>();
|
||||
Collections.addAll(flags, commonFlags);
|
||||
Collections.addAll(flags, extraFlags);
|
||||
flags.add(HumongousObjectTest.class.getName());
|
||||
|
||||
ProcessBuilder pb = ProcessTools.createTestJvm(flags);
|
||||
|
||||
OutputAnalyzer output = new OutputAnalyzer(pb.start());
|
||||
output.shouldHaveExitValue(0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This class tests that a humongous object resides in NVDIMM.
|
||||
*/
|
||||
class HumongousObjectTest {
|
||||
private static final WhiteBox WB = WhiteBox.getWhiteBox();
|
||||
|
||||
private static void validateObject(Object o) {
|
||||
Asserts.assertTrue(WB.isObjectInOldGen(o),
|
||||
"Object is supposed to be in OldGen");
|
||||
|
||||
long obj_addr = WB.getObjectAddress(o);
|
||||
long nvdimm_heap_start = WB.nvdimmReservedStart();
|
||||
long nvdimm_heap_end = WB.nvdimmReservedEnd();
|
||||
|
||||
Asserts.assertTrue(WB.g1BelongsToHumongousRegion(obj_addr), "Object address should be in Humongous set");
|
||||
Asserts.assertTrue(obj_addr >= nvdimm_heap_start && obj_addr < nvdimm_heap_end,
|
||||
"Humongous object does not reside in NVDIMM");
|
||||
}
|
||||
|
||||
public static void main(String args[]) throws Exception {
|
||||
// allocate an humongous object
|
||||
int byteArrayMemoryOverhead = Helpers.detectByteArrayAllocationOverhead();
|
||||
int MinByteArrayHumongousSize = (WB.g1RegionSize() / 2) - byteArrayMemoryOverhead + 1;
|
||||
byte[] obj = new byte[MinByteArrayHumongousSize];
|
||||
|
||||
validateObject(obj);
|
||||
}
|
||||
}
|
@ -1,109 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package gc.nvdimm;
|
||||
|
||||
/*
|
||||
* @test TestOldObjectsOnNvdimm
|
||||
* @summary Check that objects in old generation reside in dram.
|
||||
* @requires vm.gc=="null" & os.family != "aix"
|
||||
* @requires test.vm.gc.nvdimm
|
||||
* @library /test/lib
|
||||
* @build sun.hotspot.WhiteBox
|
||||
* @run driver ClassFileInstaller sun.hotspot.WhiteBox
|
||||
* @run driver gc.nvdimm.TestOldObjectsOnNvdimm
|
||||
*/
|
||||
|
||||
import jdk.test.lib.process.OutputAnalyzer;
|
||||
import jdk.test.lib.process.ProcessTools;
|
||||
import jdk.test.lib.Asserts;
|
||||
import sun.hotspot.WhiteBox;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
|
||||
/*
|
||||
* Test spawns OldObjectTest in a separate VM and expects that it
|
||||
* completes without a RuntimeException.
|
||||
*/
|
||||
public class TestOldObjectsOnNvdimm {
|
||||
|
||||
public static final int ALLOCATION_SIZE = 100;
|
||||
private static String[] commonFlags;
|
||||
|
||||
public static void main(String args[]) throws Exception {
|
||||
commonFlags = new String[] {
|
||||
"-Xbootclasspath/a:.",
|
||||
"-XX:+UnlockExperimentalVMOptions",
|
||||
"-XX:+UnlockDiagnosticVMOptions",
|
||||
"-XX:+WhiteBoxAPI",
|
||||
"-XX:AllocateOldGenAt=" + System.getProperty("test.dir", "."),
|
||||
"-Xms10M", "-Xmx10M",
|
||||
"-XX:MaxTenuringThreshold=1" // Promote objects to Old Gen
|
||||
};
|
||||
runTest("-XX:+UseG1GC");
|
||||
runTest("-XX:+UseParallelGC");
|
||||
}
|
||||
|
||||
private static void runTest(String... extraFlags) throws Exception {
|
||||
ArrayList<String> flags = new ArrayList<>();
|
||||
Collections.addAll(flags, commonFlags);
|
||||
Collections.addAll(flags, extraFlags);
|
||||
flags.add(OldObjectTest.class.getName());
|
||||
|
||||
ProcessBuilder pb = ProcessTools.createTestJvm(flags);
|
||||
|
||||
OutputAnalyzer output = new OutputAnalyzer(pb.start());
|
||||
System.out.println(output.getStdout());
|
||||
output.shouldHaveExitValue(0);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This class tests that object is in Old generation after tenuring and resides in NVDIMM.
|
||||
* The necessary condition for this test is running in VM with the following flags:
|
||||
* -XX:AllocateOldGenAt=, -XX:MaxTenuringThreshold=1
|
||||
*/
|
||||
class OldObjectTest {
|
||||
private static final WhiteBox WB = WhiteBox.getWhiteBox();
|
||||
|
||||
private static void validateOldObject(Object o) {
|
||||
Asserts.assertTrue(WB.isObjectInOldGen(o),
|
||||
"Object is supposed to be in OldGen");
|
||||
|
||||
long oldObj_addr = WB.getObjectAddress(o);
|
||||
long nvdimm_heap_start = WB.nvdimmReservedStart();
|
||||
long nvdimm_heap_end = WB.nvdimmReservedEnd();
|
||||
|
||||
Asserts.assertTrue(oldObj_addr >= nvdimm_heap_start && oldObj_addr <= nvdimm_heap_end,
|
||||
"Old object does not reside in NVDIMM");
|
||||
}
|
||||
|
||||
public static void main(String args[]) throws Exception {
|
||||
// allocate an object and perform Young GCs to promote it to Old
|
||||
byte[] oldObj = new byte[TestOldObjectsOnNvdimm.ALLOCATION_SIZE];
|
||||
WB.youngGC();
|
||||
WB.youngGC();
|
||||
validateOldObject(oldObj);
|
||||
}
|
||||
}
|
@ -1,113 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package gc.nvdimm;
|
||||
|
||||
/*
|
||||
* @test TestYoungObjectsOnDram
|
||||
* @summary Check that objects in young generation reside in dram.
|
||||
* @requires vm.gc=="null" & os.family != "aix"
|
||||
* @requires test.vm.gc.nvdimm
|
||||
* @library /test/lib
|
||||
* @build sun.hotspot.WhiteBox
|
||||
* @run driver ClassFileInstaller sun.hotspot.WhiteBox
|
||||
* @run driver gc.nvdimm.TestYoungObjectsOnDram
|
||||
*/
|
||||
|
||||
import jdk.test.lib.process.OutputAnalyzer;
|
||||
import jdk.test.lib.process.ProcessTools;
|
||||
import jdk.test.lib.Asserts;
|
||||
import sun.hotspot.WhiteBox;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
|
||||
/**
|
||||
* Test spawns YoungObjectTest in a separate VM and expects that it
|
||||
* completes without a RuntimeException.
|
||||
*/
|
||||
public class TestYoungObjectsOnDram {
|
||||
|
||||
public static final int ALLOCATION_SIZE = 100;
|
||||
private static String[] commonFlags;
|
||||
|
||||
public static void main(String args[]) throws Exception {
|
||||
commonFlags = new String[] {
|
||||
"-Xbootclasspath/a:.",
|
||||
"-XX:+UnlockExperimentalVMOptions",
|
||||
"-XX:+UnlockDiagnosticVMOptions",
|
||||
"-XX:+WhiteBoxAPI",
|
||||
"-XX:AllocateOldGenAt=" + System.getProperty("test.dir", "."),
|
||||
"-XX:SurvivorRatio=1", // Survivor-to-eden ratio is 1:1
|
||||
"-Xms10M", "-Xmx10M",
|
||||
"-XX:InitialTenuringThreshold=15" // avoid promotion of objects to Old Gen
|
||||
};
|
||||
runTest("-XX:+UseG1GC");
|
||||
runTest("-XX:+UseParallelGC");
|
||||
}
|
||||
|
||||
private static void runTest(String... extraFlags) throws Exception {
|
||||
ArrayList<String> flags = new ArrayList<>();
|
||||
Collections.addAll(flags, commonFlags);
|
||||
Collections.addAll(flags, extraFlags);
|
||||
flags.add(YoungObjectTest.class.getName());
|
||||
|
||||
ProcessBuilder pb = ProcessTools.createTestJvm(flags);
|
||||
|
||||
OutputAnalyzer output = new OutputAnalyzer(pb.start());
|
||||
System.out.println(output.getStdout());
|
||||
output.shouldHaveExitValue(0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This class tests that newly created object is in Young generation and resides in DRAM.
|
||||
* The necessary condition for this test is running in VM with the following flags:
|
||||
* -XX:AllocateOldGenAt=, -XX:InitialTenuringThreshold=15, -XX:SurvivorRatio=1
|
||||
*/
|
||||
class YoungObjectTest {
|
||||
private static final WhiteBox WB = WhiteBox.getWhiteBox();
|
||||
|
||||
private static void validateYoungObject(Object o) {
|
||||
Asserts.assertTrue(!WB.isObjectInOldGen(o),
|
||||
"Object is supposed to be in YoungGen");
|
||||
|
||||
long youngObj_addr = WB.getObjectAddress(o);
|
||||
long dram_heap_start = WB.dramReservedStart();
|
||||
long dram_heap_end = WB.dramReservedEnd();
|
||||
|
||||
Asserts.assertTrue(youngObj_addr >= dram_heap_start && youngObj_addr <= dram_heap_end,
|
||||
"Young object does not reside in DRAM");
|
||||
}
|
||||
|
||||
public static void main(String args[]) throws Exception {
|
||||
// allocate an object
|
||||
byte[] youngObj = new byte[TestYoungObjectsOnDram.ALLOCATION_SIZE];
|
||||
validateYoungObject(youngObj);
|
||||
|
||||
// Start a Young GC and check that object is still in DRAM.
|
||||
// We have used -XX:InitialTenuringThreshold=15 to invoke this test
|
||||
WB.youngGC();
|
||||
validateYoungObject(youngObj);
|
||||
}
|
||||
}
|
@ -117,7 +117,6 @@ public class VMProps implements Callable<Map<String, String>> {
|
||||
map.put("docker.support", this::dockerSupport);
|
||||
map.put("vm.musl", this::isMusl);
|
||||
map.put("release.implementor", this::implementor);
|
||||
map.put("test.vm.gc.nvdimm", this::isNvdimmTestEnabled);
|
||||
map.put("jdk.containerized", this::jdkContainerized);
|
||||
vmGC(map); // vm.gc.X = true/false
|
||||
vmOptFinalFlags(map);
|
||||
@ -541,11 +540,6 @@ public class VMProps implements Callable<Map<String, String>> {
|
||||
}
|
||||
}
|
||||
|
||||
private String isNvdimmTestEnabled() {
|
||||
String isEnabled = System.getenv("TEST_VM_GC_NVDIMM");
|
||||
return "" + "true".equalsIgnoreCase(isEnabled);
|
||||
}
|
||||
|
||||
private String jdkContainerized() {
|
||||
String isEnabled = System.getenv("TEST_JDK_CONTAINERIZED");
|
||||
return "" + "true".equalsIgnoreCase(isEnabled);
|
||||
|
@ -189,10 +189,6 @@ public class WhiteBox {
|
||||
public native long g1NumMaxRegions();
|
||||
public native long g1NumFreeRegions();
|
||||
public native int g1RegionSize();
|
||||
public native long dramReservedStart();
|
||||
public native long dramReservedEnd();
|
||||
public native long nvdimmReservedStart();
|
||||
public native long nvdimmReservedEnd();
|
||||
public native MemoryUsage g1AuxiliaryMemoryUsage();
|
||||
private native Object[] parseCommandLine0(String commandline, char delim, DiagnosticCommand[] args);
|
||||
public Object[] parseCommandLine(String commandline, char delim, DiagnosticCommand[] args) {
|
||||
|
Loading…
Reference in New Issue
Block a user