8049864: TestParallelHeapSizeFlags fails with unexpected heap size
Reviewed-by: sjohanss, jmasa
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/generationSizer.cpp Mon Sep 15 13:32:30 2014 +0000
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/generationSizer.cpp Tue Jun 24 15:50:50 2014 +0200
@@ -66,9 +66,10 @@
void GenerationSizer::initialize_size_info() {
trace_gen_sizes("ps heap raw");
- const size_t page_sz = os::page_size_for_region(_min_heap_byte_size,
- _max_heap_byte_size,
- 8);
+ const size_t max_page_sz = os::page_size_for_region(_max_heap_byte_size, 8);
+ const size_t min_pages = 4; // 1 for eden + 1 for each survivor + 1 for old
+ const size_t min_page_sz = os::page_size_for_region(_min_heap_byte_size, min_pages);
+ const size_t page_sz = MIN2(max_page_sz, min_page_sz);
// Can a page size be something else than a power of two?
assert(is_power_of_2((intptr_t)page_sz), "must be a power of 2");
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/parMarkBitMap.cpp Mon Sep 15 13:32:30 2014 +0000
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/parMarkBitMap.cpp Tue Jun 24 15:50:50 2014 +0200
@@ -41,7 +41,7 @@
const size_t words = bits / BitsPerWord;
const size_t raw_bytes = words * sizeof(idx_t);
- const size_t page_sz = os::page_size_for_region(raw_bytes, raw_bytes, 10);
+ const size_t page_sz = os::page_size_for_region(raw_bytes, 10);
const size_t granularity = os::vm_allocation_granularity();
_reserved_byte_size = align_size_up(raw_bytes, MAX2(page_sz, granularity));
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp Mon Sep 15 13:32:30 2014 +0000
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp Tue Jun 24 15:50:50 2014 +0200
@@ -403,7 +403,7 @@
ParallelCompactData::create_vspace(size_t count, size_t element_size)
{
const size_t raw_bytes = count * element_size;
- const size_t page_sz = os::page_size_for_region(raw_bytes, raw_bytes, 10);
+ const size_t page_sz = os::page_size_for_region(raw_bytes, 10);
const size_t granularity = os::vm_allocation_granularity();
_reserved_byte_size = align_size_up(raw_bytes, MAX2(page_sz, granularity));
--- a/hotspot/src/share/vm/memory/heap.cpp Mon Sep 15 13:32:30 2014 +0000
+++ b/hotspot/src/share/vm/memory/heap.cpp Tue Jun 24 15:50:50 2014 +0200
@@ -98,9 +98,13 @@
_log2_segment_size = exact_log2(segment_size);
// Reserve and initialize space for _memory.
- const size_t page_size = os::can_execute_large_page_memory() ?
- os::page_size_for_region(committed_size, reserved_size, 8) :
- os::vm_page_size();
+ size_t page_size = os::vm_page_size();
+ if (os::can_execute_large_page_memory()) {
+ const size_t min_pages = 8;
+ page_size = MIN2(os::page_size_for_region(committed_size, min_pages),
+ os::page_size_for_region(reserved_size, min_pages));
+ }
+
const size_t granularity = os::vm_allocation_granularity();
const size_t r_align = MAX2(page_size, granularity);
const size_t r_size = align_size_up(reserved_size, r_align);
--- a/hotspot/src/share/vm/prims/jni.cpp Mon Sep 15 13:32:30 2014 +0000
+++ b/hotspot/src/share/vm/prims/jni.cpp Tue Jun 24 15:50:50 2014 +0200
@@ -3848,6 +3848,7 @@
unit_test_function_call
// Forward declaration
+void TestOS_test();
void TestReservedSpace_test();
void TestReserveMemorySpecial_test();
void TestVirtualSpace_test();
@@ -3871,6 +3872,7 @@
void execute_internal_vm_tests() {
if (ExecuteInternalVMTests) {
tty->print_cr("Running internal VM tests");
+ run_unit_test(TestOS_test());
run_unit_test(TestReservedSpace_test());
run_unit_test(TestReserveMemorySpecial_test());
run_unit_test(TestVirtualSpace_test());
--- a/hotspot/src/share/vm/runtime/os.cpp Mon Sep 15 13:32:30 2014 +0000
+++ b/hotspot/src/share/vm/runtime/os.cpp Tue Jun 24 15:50:50 2014 +0200
@@ -1406,24 +1406,15 @@
return (sp > (stack_limit + reserved_area));
}
-size_t os::page_size_for_region(size_t region_min_size, size_t region_max_size,
- uint min_pages)
-{
+size_t os::page_size_for_region(size_t region_size, size_t min_pages) {
assert(min_pages > 0, "sanity");
if (UseLargePages) {
- const size_t max_page_size = region_max_size / min_pages;
+ const size_t max_page_size = region_size / min_pages;
- for (unsigned int i = 0; _page_sizes[i] != 0; ++i) {
- const size_t sz = _page_sizes[i];
- const size_t mask = sz - 1;
- if ((region_min_size & mask) == 0 && (region_max_size & mask) == 0) {
- // The largest page size with no fragmentation.
- return sz;
- }
-
- if (sz <= max_page_size) {
- // The largest page size that satisfies the min_pages requirement.
- return sz;
+ for (size_t i = 0; _page_sizes[i] != 0; ++i) {
+ const size_t page_size = _page_sizes[i];
+ if (page_size <= max_page_size && is_size_aligned(region_size, page_size)) {
+ return page_size;
}
}
}
@@ -1660,3 +1651,63 @@
return result;
}
#endif
+
+/////////////// Unit tests ///////////////
+
+#ifndef PRODUCT
+
+#define assert_eq(a,b) assert(a == b, err_msg(SIZE_FORMAT " != " SIZE_FORMAT, a, b))
+
+class TestOS : AllStatic {
+ static size_t small_page_size() {
+ return os::vm_page_size();
+ }
+
+ static size_t large_page_size() {
+ const size_t large_page_size_example = 4 * M;
+ return os::page_size_for_region(large_page_size_example, 1);
+ }
+
+ static void test_page_size_for_region() {
+ if (UseLargePages) {
+ const size_t small_page = small_page_size();
+ const size_t large_page = large_page_size();
+
+ if (large_page > small_page) {
+ size_t num_small_pages_in_large = large_page / small_page;
+ size_t page = os::page_size_for_region(large_page, num_small_pages_in_large);
+
+ assert_eq(page, small_page);
+ }
+ }
+ }
+
+ static void test_page_size_for_region_alignment() {
+ if (UseLargePages) {
+ const size_t small_page = small_page_size();
+ const size_t large_page = large_page_size();
+ if (large_page > small_page) {
+ const size_t unaligned_region = large_page + 17;
+ size_t page = os::page_size_for_region(unaligned_region, 1);
+ assert_eq(page, small_page);
+
+ const size_t num_pages = 5;
+ const size_t aligned_region = large_page * num_pages;
+ page = os::page_size_for_region(aligned_region, num_pages);
+ assert_eq(page, large_page);
+ }
+ }
+ }
+
+ public:
+ static void run_tests() {
+ test_page_size_for_region();
+ test_page_size_for_region_alignment();
+ }
+};
+
+void TestOS_test() {
+ TestOS::run_tests();
+}
+
+#endif // PRODUCT
--- a/hotspot/src/share/vm/runtime/os.hpp Mon Sep 15 13:32:30 2014 +0000
+++ b/hotspot/src/share/vm/runtime/os.hpp Tue Jun 24 15:50:50 2014 +0200
@@ -265,19 +265,11 @@
// Return the default page size.
static int vm_page_size();
- // Return the page size to use for a region of memory. The min_pages argument
- // is a hint intended to limit fragmentation; it says the returned page size
- // should be <= region_max_size / min_pages. Because min_pages is a hint,
- // this routine may return a size larger than region_max_size / min_pages.
- //
- // The current implementation ignores min_pages if a larger page size is an
- // exact multiple of both region_min_size and region_max_size. This allows
- // larger pages to be used when doing so would not cause fragmentation; in
- // particular, a single page can be used when region_min_size ==
- // region_max_size == a supported page size.
- static size_t page_size_for_region(size_t region_min_size,
- size_t region_max_size,
- uint min_pages);
+ // Returns the page size to use for a region of memory.
+ // region_size / min_pages will always be greater than or equal to the
+ // returned value.
+ static size_t page_size_for_region(size_t region_size, size_t min_pages);
+
// Return the largest page size that can be used
static size_t max_page_size() {
// The _page_sizes array is sorted in descending order.
--- a/hotspot/src/share/vm/runtime/virtualspace.cpp Mon Sep 15 13:32:30 2014 +0000
+++ b/hotspot/src/share/vm/runtime/virtualspace.cpp Tue Jun 24 15:50:50 2014 +0200
@@ -38,7 +38,7 @@
}
ReservedSpace::ReservedSpace(size_t size) {
- size_t page_size = os::page_size_for_region(size, size, 1);
+ size_t page_size = os::page_size_for_region(size, 1);
bool large_pages = page_size != (size_t)os::vm_page_size();
// Don't force the alignment to be large page aligned,
// since that will waste memory.
@@ -357,7 +357,7 @@
bool VirtualSpace::initialize(ReservedSpace rs, size_t committed_size) {
- const size_t max_commit_granularity = os::page_size_for_region(rs.size(), rs.size(), 1);
+ const size_t max_commit_granularity = os::page_size_for_region(rs.size(), 1);
return initialize_with_granularity(rs, committed_size, max_commit_granularity);
}
@@ -992,7 +992,7 @@
case Disable:
return vs.initialize_with_granularity(rs, 0, os::vm_page_size());
case Commit:
- return vs.initialize_with_granularity(rs, 0, os::page_size_for_region(rs.size(), rs.size(), 1));
+ return vs.initialize_with_granularity(rs, 0, os::page_size_for_region(rs.size(), 1));
}
}
--- a/hotspot/test/gc/arguments/TestParallelHeapSizeFlags.java Mon Sep 15 13:32:30 2014 +0000
+++ b/hotspot/test/gc/arguments/TestParallelHeapSizeFlags.java Tue Jun 24 15:50:50 2014 +0200
@@ -22,7 +22,6 @@
*/
/*
- * @ignore 8049864
* @test TestParallelHeapSizeFlags
* @key gc
* @bug 8006088