# HG changeset patch # User ehelin # Date 1403617850 -7200 # Node ID 29c97629997e5074eeae24ba19a6a4b627df7ed1 # Parent 806fe0d44237909ccaf3b215e35aebf616b68d27 8027915: TestParallelHeapSizeFlags fails with unexpected heap size on sparcv9 Reviewed-by: jmasa, sjohanss diff -r 806fe0d44237 -r 29c97629997e hotspot/src/share/vm/gc_implementation/parallelScavenge/generationSizer.cpp --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/generationSizer.cpp Mon Jun 23 14:20:20 2014 -0700 +++ 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"); diff -r 806fe0d44237 -r 29c97629997e hotspot/src/share/vm/gc_implementation/parallelScavenge/parMarkBitMap.cpp --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/parMarkBitMap.cpp Mon Jun 23 14:20:20 2014 -0700 +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/parMarkBitMap.cpp Tue Jun 24 15:50:50 2014 +0200 @@ -56,7 +56,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)); diff -r 806fe0d44237 -r 29c97629997e hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp Mon Jun 23 14:20:20 2014 -0700 +++ 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)); diff -r 806fe0d44237 -r 29c97629997e hotspot/src/share/vm/memory/heap.cpp --- a/hotspot/src/share/vm/memory/heap.cpp Mon Jun 23 14:20:20 2014 -0700 +++ 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); diff -r 806fe0d44237 -r 29c97629997e hotspot/src/share/vm/prims/jni.cpp --- a/hotspot/src/share/vm/prims/jni.cpp Mon Jun 23 14:20:20 2014 -0700 +++ b/hotspot/src/share/vm/prims/jni.cpp Tue Jun 24 15:50:50 2014 +0200 @@ -3871,6 +3871,7 @@ unit_test_function_call // Forward declaration +void TestOS_test(); void TestReservedSpace_test(); void TestReserveMemorySpecial_test(); void TestVirtualSpace_test(); @@ -3892,6 +3893,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()); diff -r 806fe0d44237 -r 29c97629997e hotspot/src/share/vm/runtime/os.cpp --- a/hotspot/src/share/vm/runtime/os.cpp Mon Jun 23 14:20:20 2014 -0700 +++ b/hotspot/src/share/vm/runtime/os.cpp Tue Jun 24 15:50:50 2014 +0200 @@ -1303,24 +1303,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; } } } @@ -1548,3 +1539,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 diff -r 806fe0d44237 -r 29c97629997e hotspot/src/share/vm/runtime/os.hpp --- a/hotspot/src/share/vm/runtime/os.hpp Mon Jun 23 14:20:20 2014 -0700 +++ b/hotspot/src/share/vm/runtime/os.hpp Tue Jun 24 15:50:50 2014 +0200 @@ -253,19 +253,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. diff -r 806fe0d44237 -r 29c97629997e hotspot/src/share/vm/runtime/virtualspace.cpp --- a/hotspot/src/share/vm/runtime/virtualspace.cpp Mon Jun 23 14:20:20 2014 -0700 +++ b/hotspot/src/share/vm/runtime/virtualspace.cpp Tue Jun 24 15:50:50 2014 +0200 @@ -53,7 +53,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. @@ -372,7 +372,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); } @@ -1007,7 +1007,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)); } } diff -r 806fe0d44237 -r 29c97629997e hotspot/test/gc/arguments/TestParallelHeapSizeFlags.java --- a/hotspot/test/gc/arguments/TestParallelHeapSizeFlags.java Mon Jun 23 14:20:20 2014 -0700 +++ b/hotspot/test/gc/arguments/TestParallelHeapSizeFlags.java Tue Jun 24 15:50:50 2014 +0200 @@ -22,7 +22,6 @@ */ /* - * @ignore 8027915 * @test TestParallelHeapSizeFlags * @key gc * @bug 8006088