--- a/hotspot/src/os/bsd/vm/os_bsd.cpp Wed Sep 11 06:15:31 2013 -0700
+++ b/hotspot/src/os/bsd/vm/os_bsd.cpp Wed Sep 11 18:47:54 2013 +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");
--- a/hotspot/src/os/linux/vm/os_linux.cpp Wed Sep 11 06:15:31 2013 -0700
+++ b/hotspot/src/os/linux/vm/os_linux.cpp Wed Sep 11 18:47:54 2013 +0200
@@ -4755,8 +4755,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");
--- a/hotspot/src/os/solaris/vm/os_solaris.cpp Wed Sep 11 06:15:31 2013 -0700
+++ b/hotspot/src/os/solaris/vm/os_solaris.cpp Wed Sep 11 18:47:54 2013 +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
--- a/hotspot/src/os/windows/vm/os_windows.cpp Wed Sep 11 06:15:31 2013 -0700
+++ b/hotspot/src/os/windows/vm/os_windows.cpp Wed Sep 11 18:47:54 2013 +0200
@@ -3920,8 +3920,6 @@
#endif
}
- os::large_page_init();
-
// Setup Windows Exceptions
// for debugging float code generation bugs
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Wed Sep 11 06:15:31 2013 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Wed Sep 11 18:47:54 2013 +0200
@@ -2191,6 +2191,10 @@
return JNI_OK;
}
+size_t G1CollectedHeap::conservative_max_heap_alignment() {
+ return HeapRegion::max_region_size();
+}
+
void G1CollectedHeap::ref_processing_init() {
// Reference processing in G1 currently works as follows:
//
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp Wed Sep 11 06:15:31 2013 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp Wed Sep 11 18:47:54 2013 +0200
@@ -1092,6 +1092,9 @@
// specified by the policy object.
jint initialize();
+ // Return the (conservative) maximum heap alignment for any G1 heap
+ static size_t conservative_max_heap_alignment();
+
// Initialize weak reference processing.
virtual void ref_processing_init();
--- a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp Wed Sep 11 06:15:31 2013 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp Wed Sep 11 18:47:54 2013 +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_region_size() {
+ return (size_t)MAX_REGION_SIZE;
+}
+
void HeapRegion::setup_heap_region_size(size_t initial_heap_size, size_t max_heap_size) {
uintx region_size = G1HeapRegionSize;
if (FLAG_IS_DEFAULT(G1HeapRegionSize)) {
--- a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp Wed Sep 11 06:15:31 2013 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp Wed Sep 11 18:47:54 2013 +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);
}
+ static size_t max_region_size();
+
// 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 /
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.hpp Wed Sep 11 06:15:31 2013 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.hpp Wed Sep 11 18:47:54 2013 +0200
@@ -86,6 +86,11 @@
set_alignment(_old_gen_alignment, intra_heap_alignment());
}
+ // Return the (conservative) maximum heap alignment
+ static size_t conservative_max_heap_alignment() {
+ return 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;
--- a/hotspot/src/share/vm/memory/collectorPolicy.cpp Wed Sep 11 06:15:31 2013 -0700
+++ b/hotspot/src/share/vm/memory/collectorPolicy.cpp Wed Sep 11 18:47:54 2013 +0200
@@ -145,6 +145,30 @@
_all_soft_refs_clear = true;
}
+size_t CollectorPolicy::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.
+
+ // 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,29 +199,6 @@
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);
--- a/hotspot/src/share/vm/memory/collectorPolicy.hpp Wed Sep 11 06:15:31 2013 -0700
+++ b/hotspot/src/share/vm/memory/collectorPolicy.hpp Wed Sep 11 18:47:54 2013 +0200
@@ -98,6 +98,9 @@
{}
public:
+ // Return maximum heap alignment that may be imposed by the policy
+ static size_t compute_max_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()
--- a/hotspot/src/share/vm/memory/genCollectedHeap.hpp Wed Sep 11 06:15:31 2013 -0700
+++ b/hotspot/src/share/vm/memory/genCollectedHeap.hpp Wed Sep 11 18:47:54 2013 +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 conservative_max_heap_alignment() {
+ return Generation::GenGrain;
+ }
+
size_t capacity() const;
size_t used() const;
--- a/hotspot/src/share/vm/memory/universe.cpp Wed Sep 11 06:15:31 2013 -0700
+++ b/hotspot/src/share/vm/memory/universe.cpp Wed Sep 11 18:47:54 2013 +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::conservative_max_heap_alignment(),
+ err_msg("actual alignment "SIZE_FORMAT" must be within maximum heap alignment "SIZE_FORMAT,
+ alignment, Arguments::conservative_max_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");
--- a/hotspot/src/share/vm/prims/whitebox.cpp Wed Sep 11 06:15:31 2013 -0700
+++ b/hotspot/src/share/vm/prims/whitebox.cpp Wed Sep 11 18:47:54 2013 +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,11 @@
return closure.found();
WB_END
+WB_ENTRY(jlong, WB_GetCompressedOopsMaxHeapSize(JNIEnv* env, jobject o)) {
+ return (jlong)Arguments::max_heap_for_compressed_oops();
+}
+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 "
@@ -436,6 +442,8 @@
CC"(Ljava/lang/String;[Lsun/hotspot/parser/DiagnosticCommand;)[Ljava/lang/Object;",
(void*) &WB_ParseCommandLine
},
+ {CC"getCompressedOopsMaxHeapSize", CC"()J",
+ (void*)&WB_GetCompressedOopsMaxHeapSize},
{CC"printHeapSizes", CC"()V", (void*)&WB_PrintHeapSizes },
#if INCLUDE_ALL_GCS
{CC"g1InConcurrentMark", CC"()Z", (void*)&WB_G1InConcurrentMark},
--- a/hotspot/src/share/vm/runtime/arguments.cpp Wed Sep 11 06:15:31 2013 -0700
+++ b/hotspot/src/share/vm/runtime/arguments.cpp Wed Sep 11 18:47:54 2013 +0200
@@ -28,6 +28,7 @@
#include "compiler/compilerOracle.hpp"
#include "memory/allocation.inline.hpp"
#include "memory/cardTableRS.hpp"
+#include "memory/genCollectedHeap.hpp"
#include "memory/referenceProcessor.hpp"
#include "memory/universe.inline.hpp"
#include "oops/oop.inline.hpp"
@@ -54,6 +55,8 @@
#endif
#if INCLUDE_ALL_GCS
#include "gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp"
+#include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
+#include "gc_implementation/parallelScavenge/parallelScavengeHeap.hpp"
#endif // INCLUDE_ALL_GCS
// Note: This is a special bug reporting site for the JVM
@@ -90,6 +93,7 @@
SystemProperty* Arguments::_system_properties = NULL;
const char* Arguments::_gc_log_filename = NULL;
bool Arguments::_has_profile = false;
+size_t Arguments::_conservative_max_heap_alignment = 0;
uintx Arguments::_min_heap_size = 0;
Arguments::Mode Arguments::_mode = _mixed;
bool Arguments::_java_compiler = false;
@@ -1391,10 +1395,17 @@
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());
+ // We need to fit both the NULL page and the heap into the memory budget, while
+ // keeping alignment constraints of the heap. To guarantee the latter, as the
+ // NULL page is located before the heap, we pad the NULL page to the conservative
+ // maximum alignment that the GC may ever impose upon the heap.
+ size_t displacement_due_to_null_page = align_size_up_(os::vm_page_size(),
+ Arguments::conservative_max_heap_alignment());
+
+ LP64_ONLY(return OopEncodingHeapMax - displacement_due_to_null_page);
NOT_LP64(ShouldNotReachHere(); return 0);
}
@@ -1475,6 +1486,23 @@
#endif // !ZERO
}
+void Arguments::set_conservative_max_heap_alignment() {
+ // The conservative maximum required alignment for the heap is the maximum of
+ // the alignments imposed by several sources: any requirements from the heap
+ // itself, the collector policy and the maximum page size we may run the VM
+ // with.
+ size_t heap_alignment = GenCollectedHeap::conservative_max_heap_alignment();
+#if INCLUDE_ALL_GCS
+ if (UseParallelGC) {
+ heap_alignment = ParallelScavengeHeap::conservative_max_heap_alignment();
+ } else if (UseG1GC) {
+ heap_alignment = G1CollectedHeap::conservative_max_heap_alignment();
+ }
+#endif // INCLUDE_ALL_GCS
+ _conservative_max_heap_alignment = MAX3(heap_alignment, os::max_page_size(),
+ CollectorPolicy::compute_max_alignment());
+}
+
void Arguments::set_ergonomics_flags() {
if (os::is_server_class_machine()) {
@@ -1503,6 +1531,8 @@
}
}
+ set_conservative_max_heap_alignment();
+
#ifndef ZERO
#ifdef _LP64
set_use_compressed_oops();
@@ -3506,6 +3536,11 @@
no_shared_spaces();
#endif // INCLUDE_CDS
+ return JNI_OK;
+}
+
+jint Arguments::apply_ergo() {
+
// Set flags based on ergonomics.
set_ergonomics_flags();
--- a/hotspot/src/share/vm/runtime/arguments.hpp Wed Sep 11 06:15:31 2013 -0700
+++ b/hotspot/src/share/vm/runtime/arguments.hpp Wed Sep 11 18:47:54 2013 +0200
@@ -280,6 +280,9 @@
// Option flags
static bool _has_profile;
static const char* _gc_log_filename;
+ // Value of the conservative maximum heap alignment needed
+ static size_t _conservative_max_heap_alignment;
+
static uintx _min_heap_size;
// -Xrun arguments
@@ -327,6 +330,7 @@
// Garbage-First (UseG1GC)
static void set_g1_gc_flags();
// GC ergonomics
+ static void set_conservative_max_heap_alignment();
static void set_use_compressed_oops();
static void set_use_compressed_klass_ptrs();
static void set_ergonomics_flags();
@@ -430,8 +434,10 @@
static char* SharedArchivePath;
public:
- // Parses the arguments
+ // Parses the arguments, first phase
static jint parse(const JavaVMInitArgs* args);
+ // Apply ergonomics
+ static jint apply_ergo();
// Adjusts the arguments after the OS have adjusted the arguments
static jint adjust_after_os();
// Check for consistency in the selection of the garbage collector.
@@ -445,6 +451,10 @@
// Used by os_solaris
static bool process_settings_file(const char* file_name, bool should_exist, jboolean ignore_unrecognized);
+ static size_t conservative_max_heap_alignment() { return _conservative_max_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; }
--- a/hotspot/src/share/vm/runtime/os.cpp Wed Sep 11 06:15:31 2013 -0700
+++ b/hotspot/src/share/vm/runtime/os.cpp Wed Sep 11 18:47:54 2013 +0200
@@ -314,6 +314,11 @@
}
}
+void os::init_before_ergo() {
+ // We need to initialize large page support here because ergonomics takes some
+ // decisions depending on large page support and the calculated large page size.
+ large_page_init();
+}
void os::signal_init() {
if (!ReduceSignalUsage) {
--- a/hotspot/src/share/vm/runtime/os.hpp Wed Sep 11 06:15:31 2013 -0700
+++ b/hotspot/src/share/vm/runtime/os.hpp Wed Sep 11 18:47:54 2013 +0200
@@ -139,7 +139,10 @@
public:
static void init(void); // Called before command line parsing
+ static void init_before_ergo(void); // Called after command line parsing
+ // before VM ergonomics processing.
static jint init_2(void); // Called after command line parsing
+ // and VM ergonomics processing
static void init_globals(void) { // Called from init_globals() in init.cpp
init_globals_ext();
}
@@ -254,6 +257,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
--- a/hotspot/src/share/vm/runtime/thread.cpp Wed Sep 11 06:15:31 2013 -0700
+++ b/hotspot/src/share/vm/runtime/thread.cpp Wed Sep 11 18:47:54 2013 +0200
@@ -3329,6 +3329,11 @@
jint parse_result = Arguments::parse(args);
if (parse_result != JNI_OK) return parse_result;
+ os::init_before_ergo();
+
+ jint ergo_result = Arguments::apply_ergo();
+ if (ergo_result != JNI_OK) return ergo_result;
+
if (PauseAtStartup) {
os::pause();
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/gc/arguments/TestUseCompressedOopsErgo.java Wed Sep 11 18:47:54 2013 +0200
@@ -0,0 +1,50 @@
+/*
+* Copyright (c) 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
+* 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.
+*/
+
+/*
+ * @test TestUseCompressedOopsErgo
+ * @key gc
+ * @bug 8010722
+ * @summary Tests ergonomics for UseCompressedOops.
+ * @library /testlibrary /testlibrary/whitebox
+ * @build TestUseCompressedOopsErgo TestUseCompressedOopsErgoTools
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * @run main/othervm TestUseCompressedOopsErgo -XX:+UseG1GC
+ * @run main/othervm TestUseCompressedOopsErgo -XX:+UseParallelGC
+ * @run main/othervm TestUseCompressedOopsErgo -XX:+UseParallelGC -XX:-UseParallelOldGC
+ * @run main/othervm TestUseCompressedOopsErgo -XX:+UseConcMarkSweepGC
+ * @run main/othervm TestUseCompressedOopsErgo -XX:+UseSerialGC
+ */
+
+public class TestUseCompressedOopsErgo {
+
+ public static void main(String args[]) throws Exception {
+ if (!TestUseCompressedOopsErgoTools.is64bitVM()) {
+ // this test is relevant for 64 bit VMs only
+ return;
+ }
+ final String[] gcFlags = args;
+ TestUseCompressedOopsErgoTools.checkCompressedOopsErgo(gcFlags);
+ }
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/gc/arguments/TestUseCompressedOopsErgoTools.java Wed Sep 11 18:47:54 2013 +0200
@@ -0,0 +1,179 @@
+/*
+* Copyright (c) 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
+* 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.
+*/
+
+import sun.management.ManagementFactoryHelper;
+import com.sun.management.HotSpotDiagnosticMXBean;
+import com.sun.management.VMOption;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.ArrayList;
+import java.util.Arrays;
+
+import com.oracle.java.testlibrary.*;
+import sun.hotspot.WhiteBox;
+
+class DetermineMaxHeapForCompressedOops {
+ public static void main(String[] args) throws Exception {
+ WhiteBox wb = WhiteBox.getWhiteBox();
+ System.out.print(wb.getCompressedOopsMaxHeapSize());
+ }
+}
+
+class TestUseCompressedOopsErgoTools {
+
+ private static long getClassMetaspaceSize() {
+ HotSpotDiagnosticMXBean diagnostic = ManagementFactoryHelper.getDiagnosticMXBean();
+
+ VMOption option = diagnostic.getVMOption("ClassMetaspaceSize");
+ return Long.parseLong(option.getValue());
+ }
+
+
+ public static long getMaxHeapForCompressedOops(String[] vmargs) throws Exception {
+ OutputAnalyzer output = runWhiteBoxTest(vmargs, DetermineMaxHeapForCompressedOops.class.getName(), new String[] {}, false);
+ return Long.parseLong(output.getStdout());
+ }
+
+ public static boolean is64bitVM() {
+ String val = System.getProperty("sun.arch.data.model");
+ if (val == null) {
+ throw new RuntimeException("Could not read sun.arch.data.model");
+ }
+ if (val.equals("64")) {
+ return true;
+ } else if (val.equals("32")) {
+ return false;
+ }
+ throw new RuntimeException("Unexpected value " + val + " of sun.arch.data.model");
+ }
+
+ /**
+ * Executes a new VM process with the given class and parameters.
+ * @param vmargs Arguments to the VM to run
+ * @param classname Name of the class to run
+ * @param arguments Arguments to the class
+ * @param useTestDotJavaDotOpts Use test.java.opts as part of the VM argument string
+ * @return The OutputAnalyzer with the results for the invocation.
+ */
+ public static OutputAnalyzer runWhiteBoxTest(String[] vmargs, String classname, String[] arguments, boolean useTestDotJavaDotOpts) throws Exception {
+ ArrayList<String> finalargs = new ArrayList<String>();
+
+ String[] whiteboxOpts = new String[] {
+ "-Xbootclasspath/a:.",
+ "-XX:+UnlockDiagnosticVMOptions", "-XX:+WhiteBoxAPI",
+ "-cp", System.getProperty("java.class.path"),
+ };
+
+ if (useTestDotJavaDotOpts) {
+ // System.getProperty("test.java.opts") is '' if no options is set,
+ // we need to skip such a result
+ String[] externalVMOpts = new String[0];
+ if (System.getProperty("test.java.opts") != null && System.getProperty("test.java.opts").length() != 0) {
+ externalVMOpts = System.getProperty("test.java.opts").split(" ");
+ }
+ finalargs.addAll(Arrays.asList(externalVMOpts));
+ }
+
+ finalargs.addAll(Arrays.asList(vmargs));
+ finalargs.addAll(Arrays.asList(whiteboxOpts));
+ finalargs.add(classname);
+ finalargs.addAll(Arrays.asList(arguments));
+
+ ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(finalargs.toArray(new String[0]));
+ OutputAnalyzer output = new OutputAnalyzer(pb.start());
+ output.shouldHaveExitValue(0);
+ return output;
+ }
+
+ private static String[] join(String[] part1, String part2) {
+ ArrayList<String> result = new ArrayList<String>();
+ result.addAll(Arrays.asList(part1));
+ result.add(part2);
+ return result.toArray(new String[0]);
+ }
+
+ public static void checkCompressedOopsErgo(String[] gcflags) throws Exception {
+ long maxHeapForCompressedOops = getMaxHeapForCompressedOops(gcflags);
+
+ checkUseCompressedOops(gcflags, maxHeapForCompressedOops, true);
+ checkUseCompressedOops(gcflags, maxHeapForCompressedOops - 1, true);
+ checkUseCompressedOops(gcflags, maxHeapForCompressedOops + 1, false);
+
+ // the use of HeapBaseMinAddress should not change the outcome
+ checkUseCompressedOops(join(gcflags, "-XX:HeapBaseMinAddress=32G"), maxHeapForCompressedOops, true);
+ checkUseCompressedOops(join(gcflags, "-XX:HeapBaseMinAddress=32G"), maxHeapForCompressedOops - 1, true);
+ checkUseCompressedOops(join(gcflags, "-XX:HeapBaseMinAddress=32G"), maxHeapForCompressedOops + 1, false);
+
+ // use a different object alignment
+ maxHeapForCompressedOops = getMaxHeapForCompressedOops(join(gcflags, "-XX:ObjectAlignmentInBytes=16"));
+
+ checkUseCompressedOops(join(gcflags, "-XX:ObjectAlignmentInBytes=16"), maxHeapForCompressedOops, true);
+ checkUseCompressedOops(join(gcflags, "-XX:ObjectAlignmentInBytes=16"), maxHeapForCompressedOops - 1, true);
+ checkUseCompressedOops(join(gcflags, "-XX:ObjectAlignmentInBytes=16"), maxHeapForCompressedOops + 1, false);
+
+ // use a different ClassMetaspaceSize
+ String classMetaspaceSizeArg = "-XX:ClassMetaspaceSize=" + 2 * getClassMetaspaceSize();
+ maxHeapForCompressedOops = getMaxHeapForCompressedOops(join(gcflags, classMetaspaceSizeArg));
+
+ checkUseCompressedOops(join(gcflags, classMetaspaceSizeArg), maxHeapForCompressedOops, true);
+ checkUseCompressedOops(join(gcflags, classMetaspaceSizeArg), maxHeapForCompressedOops - 1, true);
+ checkUseCompressedOops(join(gcflags, classMetaspaceSizeArg), maxHeapForCompressedOops + 1, false);
+ }
+
+ private static void checkUseCompressedOops(String[] args, long heapsize, boolean expectUseCompressedOops) throws Exception {
+ ArrayList<String> finalargs = new ArrayList<String>();
+ finalargs.addAll(Arrays.asList(args));
+ finalargs.add("-Xmx" + heapsize);
+ finalargs.add("-XX:+PrintFlagsFinal");
+ finalargs.add("-version");
+
+ String output = expectValid(finalargs.toArray(new String[0]));
+
+ boolean actualUseCompressedOops = getFlagBoolValue(" UseCompressedOops", output);
+
+ if (expectUseCompressedOops != actualUseCompressedOops) {
+ throw new RuntimeException("Expected use of compressed oops: " + expectUseCompressedOops + " but was: " + actualUseCompressedOops);
+ }
+ }
+
+ private static boolean getFlagBoolValue(String flag, String where) {
+ Matcher m = Pattern.compile(flag + "\\s+:?= (true|false)").matcher(where);
+ if (!m.find()) {
+ throw new RuntimeException("Could not find value for flag " + flag + " in output string");
+ }
+ String match = m.group(1).equals("true");
+ }
+
+ private static String expect(String[] flags, boolean hasWarning, boolean hasError, int errorcode) throws Exception {
+ ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(flags);
+ OutputAnalyzer output = new OutputAnalyzer(pb.start());
+ output.shouldHaveExitValue(errorcode);
+ return output.getStdout();
+ }
+
+ private static String expectValid(String[] flags) throws Exception {
+ return expect(flags, false, false, 0);
+ }
+}
+
--- a/hotspot/test/testlibrary/whitebox/sun/hotspot/WhiteBox.java Wed Sep 11 06:15:31 2013 -0700
+++ b/hotspot/test/testlibrary/whitebox/sun/hotspot/WhiteBox.java Wed Sep 11 18:47:54 2013 +0200
@@ -61,6 +61,8 @@
registerNatives();
}
+ // Get the maximum heap size supporting COOPs
+ public native long getCompressedOopsMaxHeapSize();
// Arguments
public native void printHeapSizes();