--- old/src/os/bsd/vm/os_bsd.cpp 2013-08-28 14:34:25.504178881 +0200 +++ new/src/os/bsd/vm/os_bsd.cpp 2013-08-28 14:34:25.444178883 +0200 @@ -3589,8 +3589,6 @@ #endif } - os::large_page_init(); - // initialize suspend/resume support - must do this before signal_sets_init() if (SR_initialize() != 0) { perror("SR_initialize failed"); --- old/src/os/linux/vm/os_linux.cpp 2013-08-28 14:34:25.940178869 +0200 +++ new/src/os/linux/vm/os_linux.cpp 2013-08-28 14:34:25.876178871 +0200 @@ -4715,8 +4715,6 @@ #endif } - os::large_page_init(); - // initialize suspend/resume support - must do this before signal_sets_init() if (SR_initialize() != 0) { perror("SR_initialize failed"); --- old/src/os/solaris/vm/os_solaris.cpp 2013-08-28 14:34:26.416178856 +0200 +++ new/src/os/solaris/vm/os_solaris.cpp 2013-08-28 14:34:26.356178858 +0200 @@ -5178,9 +5178,7 @@ if(Verbose && PrintMiscellaneous) tty->print("[Memory Serialize Page address: " INTPTR_FORMAT "]\n", (intptr_t)mem_serialize_page); #endif -} - - os::large_page_init(); + } // Check minimum allowable stack size for thread creation and to initialize // the java system classes, including StackOverflowError - depends on page --- old/src/os/windows/vm/os_windows.cpp 2013-08-28 14:34:26.856178845 +0200 +++ new/src/os/windows/vm/os_windows.cpp 2013-08-28 14:34:26.796178846 +0200 @@ -3917,8 +3917,6 @@ #endif } - os::large_page_init(); - // Setup Windows Exceptions // for debugging float code generation bugs --- old/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp 2013-08-28 14:34:27.332178832 +0200 +++ new/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp 2013-08-28 14:34:27.264178833 +0200 @@ -2189,6 +2189,10 @@ return JNI_OK; } +size_t G1CollectedHeap::max_heap_alignment() { + return HeapRegion::max_heap_alignment(); +} + void G1CollectedHeap::ref_processing_init() { // Reference processing in G1 currently works as follows: // --- old/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp 2013-08-28 14:34:27.788178819 +0200 +++ new/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp 2013-08-28 14:34:27.728178821 +0200 @@ -1091,6 +1091,9 @@ // specified by the policy object. jint initialize(); + // return the (conservative) maximum heap alignment for any G1 heap + static size_t max_heap_alignment(); + // Initialize weak reference processing. virtual void ref_processing_init(); --- old/src/share/vm/gc_implementation/g1/heapRegion.cpp 2013-08-28 14:34:28.184178809 +0200 +++ new/src/share/vm/gc_implementation/g1/heapRegion.cpp 2013-08-28 14:34:28.124178810 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2013, 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 @@ -149,6 +149,10 @@ // many regions in the heap (based on the min heap size). #define TARGET_REGION_NUMBER 2048 +size_t HeapRegion::max_heap_alignment() { + return (size_t)MAX_REGION_SIZE; +} + void HeapRegion::setup_heap_region_size(uintx min_heap_size) { // region_size in bytes uintx region_size = G1HeapRegionSize; --- old/src/share/vm/gc_implementation/g1/heapRegion.hpp 2013-08-28 14:34:28.588178798 +0200 +++ new/src/share/vm/gc_implementation/g1/heapRegion.hpp 2013-08-28 14:34:28.532178799 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2013, 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 @@ -355,6 +355,8 @@ ~((1 << (size_t) LogOfHRGrainBytes) - 1); } + // return the (conservative) maximum heap alignment for any heap region + static size_t max_heap_alignment(); // It sets up the heap region size (GrainBytes / GrainWords), as // well as other related fields that are based on the heap region // size (LogOfHRGrainBytes / LogOfHRGrainWords / --- old/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.hpp 2013-08-28 14:34:28.976178787 +0200 +++ new/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.hpp 2013-08-28 14:34:28.920178789 +0200 @@ -86,6 +86,11 @@ set_alignment(_old_gen_alignment, intra_heap_alignment()); } + // return the (conservative) maximum heap alignment + static size_t max_heap_alignment() { + return MAX2(os::max_page_size(), intra_heap_alignment()); + } + // For use by VM operations enum CollectionType { Scavenge, @@ -122,7 +127,7 @@ // The alignment used for eden and survivors within the young gen // and for boundary between young gen and old gen. - size_t intra_heap_alignment() const { return 64 * K * HeapWordSize; } + static size_t intra_heap_alignment() { return 64 * K * HeapWordSize; } size_t capacity() const; size_t used() const; --- old/src/share/vm/memory/collectorPolicy.cpp 2013-08-28 14:34:29.348178777 +0200 +++ new/src/share/vm/memory/collectorPolicy.cpp 2013-08-28 14:34:29.296178778 +0200 @@ -145,6 +145,30 @@ _all_soft_refs_clear = true; } +size_t CollectorPolicy::compute_largest_heap_alignment() { + // The card marking array and the offset arrays for old generations are + // committed in os pages as well. Make sure they are entirely full (to + // avoid partial page problems), e.g. if 512 bytes heap corresponds to 1 + // byte entry and the os page size is 4096, the maximum heap size should + // be 512*4096 = 2MB aligned. + + // there is only the GenRemSet in Hotspot and only the GenRemSet::CardTable + // is supported. + // Requirements of any new remembered set implementations must be added here. + size_t alignment = GenRemSet::max_alignment_constraint(GenRemSet::CardTable); + + // Parallel GC does its own alignment of the generations to avoid requiring a + // large page (256M on some platforms) for the permanent generation. The + // other collectors should also be updated to do their own alignment and then + // this use of lcm() should be removed. + if (UseLargePages && !UseParallelGC) { + // in presence of large pages we have to make sure that our + // alignment is large page aware + alignment = lcm(os::large_page_size(), alignment); + } + + return alignment; +} // GenCollectorPolicy methods. @@ -175,33 +199,10 @@ GCTimeRatio); } -size_t GenCollectorPolicy::compute_max_alignment() { - // The card marking array and the offset arrays for old generations are - // committed in os pages as well. Make sure they are entirely full (to - // avoid partial page problems), e.g. if 512 bytes heap corresponds to 1 - // byte entry and the os page size is 4096, the maximum heap size should - // be 512*4096 = 2MB aligned. - size_t alignment = GenRemSet::max_alignment_constraint(rem_set_name()); - - // Parallel GC does its own alignment of the generations to avoid requiring a - // large page (256M on some platforms) for the permanent generation. The - // other collectors should also be updated to do their own alignment and then - // this use of lcm() should be removed. - if (UseLargePages && !UseParallelGC) { - // in presence of large pages we have to make sure that our - // alignment is large page aware - alignment = lcm(os::large_page_size(), alignment); - } - - assert(alignment >= min_alignment(), "Must be"); - - return alignment; -} - void GenCollectorPolicy::initialize_flags() { // All sizes must be multiples of the generation granularity. set_min_alignment((uintx) Generation::GenGrain); - set_max_alignment(compute_max_alignment()); + set_max_alignment(compute_largest_heap_alignment()); CollectorPolicy::initialize_flags(); --- old/src/share/vm/memory/collectorPolicy.hpp 2013-08-28 14:34:29.732178767 +0200 +++ new/src/share/vm/memory/collectorPolicy.hpp 2013-08-28 14:34:29.680178768 +0200 @@ -98,6 +98,9 @@ {} public: + // return maximum heap alignment that may be imposed by the policy + static size_t compute_largest_heap_alignment(); + void set_min_alignment(size_t align) { _min_alignment = align; } size_t min_alignment() { return _min_alignment; } void set_max_alignment(size_t align) { _max_alignment = align; } @@ -234,9 +237,6 @@ // Try to allocate space by expanding the heap. virtual HeapWord* expand_heap_and_allocate(size_t size, bool is_tlab); - // compute max heap alignment - size_t compute_max_alignment(); - // Scale the base_size by NewRation according to // result = base_size / (NewRatio + 1) // and align by min_alignment() --- old/src/share/vm/memory/genCollectedHeap.hpp 2013-08-28 14:34:30.104178756 +0200 +++ new/src/share/vm/memory/genCollectedHeap.hpp 2013-08-28 14:34:30.044178758 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2013, 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 @@ -148,6 +148,11 @@ return gen_policy()->size_policy(); } + // return the (conservative) maximum heap alignment + static size_t max_heap_alignment() { + return Generation::GenGrain; + } + size_t capacity() const; size_t used() const; --- old/src/share/vm/memory/universe.cpp 2013-08-28 14:34:30.480178746 +0200 +++ new/src/share/vm/memory/universe.cpp 2013-08-28 14:34:30.428178748 +0200 @@ -872,6 +872,9 @@ // Reserve the Java heap, which is now the same for all GCs. ReservedSpace Universe::reserve_heap(size_t heap_size, size_t alignment) { + assert(alignment <= Arguments::largest_heap_alignment(), + err_msg("actual alignment %zd must be within maximum heap alignment %zd", + alignment, Arguments::largest_heap_alignment())); size_t total_reserved = align_size_up(heap_size, alignment); assert(!UseCompressedOops || (total_reserved <= (OopEncodingHeapMax - os::vm_page_size())), "heap size is too big for compressed oops"); --- old/src/share/vm/prims/whitebox.cpp 2013-08-28 14:34:30.884178735 +0200 +++ new/src/share/vm/prims/whitebox.cpp 2013-08-28 14:34:30.824178737 +0200 @@ -33,6 +33,7 @@ #include "prims/whitebox.hpp" #include "prims/wbtestmethods/parserTests.hpp" +#include "runtime/arguments.hpp" #include "runtime/interfaceSupport.hpp" #include "runtime/os.hpp" #include "utilities/debug.hpp" @@ -94,6 +95,12 @@ return closure.found(); WB_END +WB_ENTRY(void, WB_PrintCompressedOopsHeapInfo(JNIEnv* env, jobject o)) { + gclog_or_tty->print_cr("Max heap for compressed oops "SIZE_FORMAT" ClassMetaspaceSize "SIZE_FORMAT, + Arguments::max_heap_for_compressed_oops(), ClassMetaspaceSize); +} +WB_END + WB_ENTRY(void, WB_PrintHeapSizes(JNIEnv* env, jobject o)) { CollectorPolicy * p = Universe::heap()->collector_policy(); gclog_or_tty->print_cr("Minimum heap "SIZE_FORMAT" Initial heap " @@ -432,6 +439,9 @@ CC"(Ljava/lang/String;[Lsun/hotspot/parser/DiagnosticCommand;)[Ljava/lang/Object;", (void*) &WB_ParseCommandLine }, + {CC"printCompressedOopsHeapInfo", + CC"()V", + (void*)&WB_PrintCompressedOopsHeapInfo}, {CC"printHeapSizes", CC"()V", (void*)&WB_PrintHeapSizes }, #if INCLUDE_ALL_GCS {CC"g1InConcurrentMark", CC"()Z", (void*)&WB_G1InConcurrentMark}, --- old/src/share/vm/runtime/arguments.cpp 2013-08-28 14:34:31.276178725 +0200 +++ new/src/share/vm/runtime/arguments.cpp 2013-08-28 14:34:31.204178727 +0200 @@ -52,7 +52,10 @@ #ifdef TARGET_OS_FAMILY_bsd # include "os_bsd.inline.hpp" #endif +#include "memory/genCollectedHeap.hpp" #if INCLUDE_ALL_GCS +#include "gc_implementation/parallelScavenge/parallelScavengeHeap.hpp" +#include "gc_implementation/g1/g1CollectedHeap.inline.hpp" #include "gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp" #endif // INCLUDE_ALL_GCS @@ -90,6 +93,7 @@ SystemProperty* Arguments::_system_properties = NULL; const char* Arguments::_gc_log_filename = NULL; bool Arguments::_has_profile = false; +size_t Arguments::_largest_heap_alignment = 0; uintx Arguments::_min_heap_size = 0; Arguments::Mode Arguments::_mode = _mixed; bool Arguments::_java_compiler = false; @@ -1391,10 +1395,12 @@ return true; } -inline uintx max_heap_for_compressed_oops() { +uintx Arguments::max_heap_for_compressed_oops() { // Avoid sign flip. assert(OopEncodingHeapMax > (uint64_t)os::vm_page_size(), "Unusual page size"); - LP64_ONLY(return OopEncodingHeapMax - os::vm_page_size()); + size_t aligned_null_page_size = align_size_up_(os::vm_page_size(), Arguments::largest_heap_alignment()); + + LP64_ONLY(return OopEncodingHeapMax - aligned_null_page_size); NOT_LP64(ShouldNotReachHere(); return 0); } @@ -1475,6 +1481,23 @@ #endif // !ZERO } +void Arguments::set_largest_max_heap_alignment() { + size_t gc_alignment; +#if INCLUDE_ALL_GCS + if (UseParallelGC) { + gc_alignment = ParallelScavengeHeap::max_heap_alignment(); + } else if (UseG1GC) { + gc_alignment = G1CollectedHeap::max_heap_alignment(); + } else { +#endif // INCLUDE_ALL_GCS + gc_alignment = GenCollectedHeap::max_heap_alignment(); +#if INCLUDE_ALL_GCS + } +#endif // INCLUDE_ALL_GCS + _largest_heap_alignment = MAX3(gc_alignment, os::max_page_size(), + CollectorPolicy::compute_largest_heap_alignment()); +} + void Arguments::set_ergonomics_flags() { if (os::is_server_class_machine()) { @@ -1503,6 +1526,8 @@ } } + set_largest_max_heap_alignment(); + #ifndef ZERO #ifdef _LP64 set_use_compressed_oops(); @@ -3517,6 +3542,11 @@ no_shared_spaces(); #endif // INCLUDE_CDS + // We need to initialize large page support here because ergonomics takes some + // decisions depending on large page support and the calculated large page size. + // Ergonomics may turn off large page support off later again. + os::large_page_init(); + // Set flags based on ergonomics. set_ergonomics_flags(); --- old/src/share/vm/runtime/arguments.hpp 2013-08-28 14:34:31.700178713 +0200 +++ new/src/share/vm/runtime/arguments.hpp 2013-08-28 14:34:31.640178715 +0200 @@ -263,6 +263,9 @@ // Option flags static bool _has_profile; static const char* _gc_log_filename; + // computed value for the largest heap alignment needed for any GC + static size_t _largest_heap_alignment; + static uintx _min_heap_size; // -Xrun arguments @@ -308,6 +311,7 @@ // Garbage-First (UseG1GC) static void set_g1_gc_flags(); // GC ergonomics + static void set_largest_max_heap_alignment(); static void set_use_compressed_oops(); static void set_use_compressed_klass_ptrs(); static void set_ergonomics_flags(); @@ -428,6 +432,10 @@ // Used by os_solaris static bool process_settings_file(const char* file_name, bool should_exist, jboolean ignore_unrecognized); + static size_t largest_heap_alignment() { return _largest_heap_alignment; } + // return the maximum size a heap with compressed oops can take + static size_t max_heap_for_compressed_oops(); + // return a char* array containing all options static char** jvm_flags_array() { return _jvm_flags_array; } static char** jvm_args_array() { return _jvm_args_array; } --- old/src/share/vm/runtime/os.hpp 2013-08-28 14:34:32.100178702 +0200 +++ new/src/share/vm/runtime/os.hpp 2013-08-28 14:34:32.040178704 +0200 @@ -252,6 +252,11 @@ static size_t page_size_for_region(size_t region_min_size, size_t region_max_size, uint 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. + return _page_sizes[0]; + } // Methods for tracing page sizes returned by the above method; enabled by // TracePageSizes. The region_{min,max}_size parameters should be the values --- old/test/testlibrary/whitebox/sun/hotspot/WhiteBox.java 2013-08-28 14:34:32.516178691 +0200 +++ new/test/testlibrary/whitebox/sun/hotspot/WhiteBox.java 2013-08-28 14:34:32.452178693 +0200 @@ -61,6 +61,8 @@ registerNatives(); } + // print information about compressed oops + public native void printCompressedOopsHeapInfo(); // Arguments public native void printHeapSizes();