提交 95a96a89 编写于 作者: T tschatzl

8010722: assert: failed: heap size is too big for compressed oops

Summary: Use conservative assumptions of required alignment for the various garbage collector components into account when determining the maximum heap size that supports compressed oops. Using this conservative value avoids several circular dependencies in the calculation.
Reviewed-by: stefank, dholmes
上级 91e4f7e3
...@@ -3589,8 +3589,6 @@ jint os::init_2(void) ...@@ -3589,8 +3589,6 @@ jint os::init_2(void)
#endif #endif
} }
os::large_page_init();
// initialize suspend/resume support - must do this before signal_sets_init() // initialize suspend/resume support - must do this before signal_sets_init()
if (SR_initialize() != 0) { if (SR_initialize() != 0) {
perror("SR_initialize failed"); perror("SR_initialize failed");
......
...@@ -4755,8 +4755,6 @@ jint os::init_2(void) ...@@ -4755,8 +4755,6 @@ jint os::init_2(void)
#endif #endif
} }
os::large_page_init();
// initialize suspend/resume support - must do this before signal_sets_init() // initialize suspend/resume support - must do this before signal_sets_init()
if (SR_initialize() != 0) { if (SR_initialize() != 0) {
perror("SR_initialize failed"); perror("SR_initialize failed");
......
...@@ -5178,9 +5178,7 @@ jint os::init_2(void) { ...@@ -5178,9 +5178,7 @@ jint os::init_2(void) {
if(Verbose && PrintMiscellaneous) if(Verbose && PrintMiscellaneous)
tty->print("[Memory Serialize Page address: " INTPTR_FORMAT "]\n", (intptr_t)mem_serialize_page); tty->print("[Memory Serialize Page address: " INTPTR_FORMAT "]\n", (intptr_t)mem_serialize_page);
#endif #endif
} }
os::large_page_init();
// Check minimum allowable stack size for thread creation and to initialize // Check minimum allowable stack size for thread creation and to initialize
// the java system classes, including StackOverflowError - depends on page // the java system classes, including StackOverflowError - depends on page
......
...@@ -3920,8 +3920,6 @@ jint os::init_2(void) { ...@@ -3920,8 +3920,6 @@ jint os::init_2(void) {
#endif #endif
} }
os::large_page_init();
// Setup Windows Exceptions // Setup Windows Exceptions
// for debugging float code generation bugs // for debugging float code generation bugs
......
...@@ -2191,6 +2191,10 @@ jint G1CollectedHeap::initialize() { ...@@ -2191,6 +2191,10 @@ jint G1CollectedHeap::initialize() {
return JNI_OK; return JNI_OK;
} }
size_t G1CollectedHeap::conservative_max_heap_alignment() {
return HeapRegion::max_region_size();
}
void G1CollectedHeap::ref_processing_init() { void G1CollectedHeap::ref_processing_init() {
// Reference processing in G1 currently works as follows: // Reference processing in G1 currently works as follows:
// //
......
...@@ -1092,6 +1092,9 @@ public: ...@@ -1092,6 +1092,9 @@ public:
// specified by the policy object. // specified by the policy object.
jint initialize(); jint initialize();
// Return the (conservative) maximum heap alignment for any G1 heap
static size_t conservative_max_heap_alignment();
// Initialize weak reference processing. // Initialize weak reference processing.
virtual void ref_processing_init(); virtual void ref_processing_init();
......
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -149,6 +149,10 @@ void HeapRegionDCTOC::walk_mem_region_with_cl(MemRegion mr, ...@@ -149,6 +149,10 @@ void HeapRegionDCTOC::walk_mem_region_with_cl(MemRegion mr,
// many regions in the heap (based on the min heap size). // many regions in the heap (based on the min heap size).
#define TARGET_REGION_NUMBER 2048 #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) { void HeapRegion::setup_heap_region_size(size_t initial_heap_size, size_t max_heap_size) {
uintx region_size = G1HeapRegionSize; uintx region_size = G1HeapRegionSize;
if (FLAG_IS_DEFAULT(G1HeapRegionSize)) { if (FLAG_IS_DEFAULT(G1HeapRegionSize)) {
......
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -355,6 +355,8 @@ class HeapRegion: public G1OffsetTableContigSpace { ...@@ -355,6 +355,8 @@ class HeapRegion: public G1OffsetTableContigSpace {
~((1 << (size_t) LogOfHRGrainBytes) - 1); ~((1 << (size_t) LogOfHRGrainBytes) - 1);
} }
static size_t max_region_size();
// It sets up the heap region size (GrainBytes / GrainWords), as // It sets up the heap region size (GrainBytes / GrainWords), as
// well as other related fields that are based on the heap region // well as other related fields that are based on the heap region
// size (LogOfHRGrainBytes / LogOfHRGrainWords / // size (LogOfHRGrainBytes / LogOfHRGrainWords /
......
...@@ -86,6 +86,11 @@ class ParallelScavengeHeap : public CollectedHeap { ...@@ -86,6 +86,11 @@ class ParallelScavengeHeap : public CollectedHeap {
set_alignment(_old_gen_alignment, intra_heap_alignment()); 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 // For use by VM operations
enum CollectionType { enum CollectionType {
Scavenge, Scavenge,
...@@ -122,7 +127,7 @@ class ParallelScavengeHeap : public CollectedHeap { ...@@ -122,7 +127,7 @@ class ParallelScavengeHeap : public CollectedHeap {
// The alignment used for eden and survivors within the young gen // The alignment used for eden and survivors within the young gen
// and for boundary between young gen and old 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 capacity() const;
size_t used() const; size_t used() const;
......
...@@ -145,6 +145,30 @@ void CollectorPolicy::cleared_all_soft_refs() { ...@@ -145,6 +145,30 @@ void CollectorPolicy::cleared_all_soft_refs() {
_all_soft_refs_clear = true; _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. // GenCollectorPolicy methods.
...@@ -175,29 +199,6 @@ void GenCollectorPolicy::initialize_size_policy(size_t init_eden_size, ...@@ -175,29 +199,6 @@ void GenCollectorPolicy::initialize_size_policy(size_t init_eden_size,
GCTimeRatio); 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() { void GenCollectorPolicy::initialize_flags() {
// All sizes must be multiples of the generation granularity. // All sizes must be multiples of the generation granularity.
set_min_alignment((uintx) Generation::GenGrain); set_min_alignment((uintx) Generation::GenGrain);
......
...@@ -98,6 +98,9 @@ class CollectorPolicy : public CHeapObj<mtGC> { ...@@ -98,6 +98,9 @@ class CollectorPolicy : public CHeapObj<mtGC> {
{} {}
public: 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; } void set_min_alignment(size_t align) { _min_alignment = align; }
size_t min_alignment() { return _min_alignment; } size_t min_alignment() { return _min_alignment; }
void set_max_alignment(size_t align) { _max_alignment = align; } void set_max_alignment(size_t align) { _max_alignment = align; }
...@@ -234,9 +237,6 @@ class GenCollectorPolicy : public CollectorPolicy { ...@@ -234,9 +237,6 @@ class GenCollectorPolicy : public CollectorPolicy {
// Try to allocate space by expanding the heap. // Try to allocate space by expanding the heap.
virtual HeapWord* expand_heap_and_allocate(size_t size, bool is_tlab); 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 // Scale the base_size by NewRation according to
// result = base_size / (NewRatio + 1) // result = base_size / (NewRatio + 1)
// and align by min_alignment() // and align by min_alignment()
......
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -148,6 +148,11 @@ public: ...@@ -148,6 +148,11 @@ public:
return gen_policy()->size_policy(); 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 capacity() const;
size_t used() const; size_t used() const;
......
...@@ -872,6 +872,9 @@ jint Universe::initialize_heap() { ...@@ -872,6 +872,9 @@ jint Universe::initialize_heap() {
// Reserve the Java heap, which is now the same for all GCs. // Reserve the Java heap, which is now the same for all GCs.
ReservedSpace Universe::reserve_heap(size_t heap_size, size_t alignment) { 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); size_t total_reserved = align_size_up(heap_size, alignment);
assert(!UseCompressedOops || (total_reserved <= (OopEncodingHeapMax - os::vm_page_size())), assert(!UseCompressedOops || (total_reserved <= (OopEncodingHeapMax - os::vm_page_size())),
"heap size is too big for compressed oops"); "heap size is too big for compressed oops");
......
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
#include "prims/whitebox.hpp" #include "prims/whitebox.hpp"
#include "prims/wbtestmethods/parserTests.hpp" #include "prims/wbtestmethods/parserTests.hpp"
#include "runtime/arguments.hpp"
#include "runtime/interfaceSupport.hpp" #include "runtime/interfaceSupport.hpp"
#include "runtime/os.hpp" #include "runtime/os.hpp"
#include "utilities/debug.hpp" #include "utilities/debug.hpp"
...@@ -94,6 +95,11 @@ WB_ENTRY(jboolean, WB_IsClassAlive(JNIEnv* env, jobject target, jstring name)) ...@@ -94,6 +95,11 @@ WB_ENTRY(jboolean, WB_IsClassAlive(JNIEnv* env, jobject target, jstring name))
return closure.found(); return closure.found();
WB_END 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)) { WB_ENTRY(void, WB_PrintHeapSizes(JNIEnv* env, jobject o)) {
CollectorPolicy * p = Universe::heap()->collector_policy(); CollectorPolicy * p = Universe::heap()->collector_policy();
gclog_or_tty->print_cr("Minimum heap "SIZE_FORMAT" Initial heap " gclog_or_tty->print_cr("Minimum heap "SIZE_FORMAT" Initial heap "
...@@ -436,6 +442,8 @@ static JNINativeMethod methods[] = { ...@@ -436,6 +442,8 @@ static JNINativeMethod methods[] = {
CC"(Ljava/lang/String;[Lsun/hotspot/parser/DiagnosticCommand;)[Ljava/lang/Object;", CC"(Ljava/lang/String;[Lsun/hotspot/parser/DiagnosticCommand;)[Ljava/lang/Object;",
(void*) &WB_ParseCommandLine (void*) &WB_ParseCommandLine
}, },
{CC"getCompressedOopsMaxHeapSize", CC"()J",
(void*)&WB_GetCompressedOopsMaxHeapSize},
{CC"printHeapSizes", CC"()V", (void*)&WB_PrintHeapSizes }, {CC"printHeapSizes", CC"()V", (void*)&WB_PrintHeapSizes },
#if INCLUDE_ALL_GCS #if INCLUDE_ALL_GCS
{CC"g1InConcurrentMark", CC"()Z", (void*)&WB_G1InConcurrentMark}, {CC"g1InConcurrentMark", CC"()Z", (void*)&WB_G1InConcurrentMark},
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#include "compiler/compilerOracle.hpp" #include "compiler/compilerOracle.hpp"
#include "memory/allocation.inline.hpp" #include "memory/allocation.inline.hpp"
#include "memory/cardTableRS.hpp" #include "memory/cardTableRS.hpp"
#include "memory/genCollectedHeap.hpp"
#include "memory/referenceProcessor.hpp" #include "memory/referenceProcessor.hpp"
#include "memory/universe.inline.hpp" #include "memory/universe.inline.hpp"
#include "oops/oop.inline.hpp" #include "oops/oop.inline.hpp"
...@@ -54,6 +55,8 @@ ...@@ -54,6 +55,8 @@
#endif #endif
#if INCLUDE_ALL_GCS #if INCLUDE_ALL_GCS
#include "gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp" #include "gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp"
#include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
#include "gc_implementation/parallelScavenge/parallelScavengeHeap.hpp"
#endif // INCLUDE_ALL_GCS #endif // INCLUDE_ALL_GCS
// Note: This is a special bug reporting site for the JVM // Note: This is a special bug reporting site for the JVM
...@@ -90,6 +93,7 @@ char* Arguments::_java_command = NULL; ...@@ -90,6 +93,7 @@ char* Arguments::_java_command = NULL;
SystemProperty* Arguments::_system_properties = NULL; SystemProperty* Arguments::_system_properties = NULL;
const char* Arguments::_gc_log_filename = NULL; const char* Arguments::_gc_log_filename = NULL;
bool Arguments::_has_profile = false; bool Arguments::_has_profile = false;
size_t Arguments::_conservative_max_heap_alignment = 0;
uintx Arguments::_min_heap_size = 0; uintx Arguments::_min_heap_size = 0;
Arguments::Mode Arguments::_mode = _mixed; Arguments::Mode Arguments::_mode = _mixed;
bool Arguments::_java_compiler = false; bool Arguments::_java_compiler = false;
...@@ -1391,10 +1395,17 @@ bool verify_object_alignment() { ...@@ -1391,10 +1395,17 @@ bool verify_object_alignment() {
return true; return true;
} }
inline uintx max_heap_for_compressed_oops() { uintx Arguments::max_heap_for_compressed_oops() {
// Avoid sign flip. // Avoid sign flip.
assert(OopEncodingHeapMax > (uint64_t)os::vm_page_size(), "Unusual page size"); 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); NOT_LP64(ShouldNotReachHere(); return 0);
} }
...@@ -1475,6 +1486,23 @@ void Arguments::set_use_compressed_klass_ptrs() { ...@@ -1475,6 +1486,23 @@ void Arguments::set_use_compressed_klass_ptrs() {
#endif // !ZERO #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() { void Arguments::set_ergonomics_flags() {
if (os::is_server_class_machine()) { if (os::is_server_class_machine()) {
...@@ -1503,6 +1531,8 @@ void Arguments::set_ergonomics_flags() { ...@@ -1503,6 +1531,8 @@ void Arguments::set_ergonomics_flags() {
} }
} }
set_conservative_max_heap_alignment();
#ifndef ZERO #ifndef ZERO
#ifdef _LP64 #ifdef _LP64
set_use_compressed_oops(); set_use_compressed_oops();
...@@ -3506,6 +3536,11 @@ jint Arguments::parse(const JavaVMInitArgs* args) { ...@@ -3506,6 +3536,11 @@ jint Arguments::parse(const JavaVMInitArgs* args) {
no_shared_spaces(); no_shared_spaces();
#endif // INCLUDE_CDS #endif // INCLUDE_CDS
return JNI_OK;
}
jint Arguments::apply_ergo() {
// Set flags based on ergonomics. // Set flags based on ergonomics.
set_ergonomics_flags(); set_ergonomics_flags();
......
...@@ -280,6 +280,9 @@ class Arguments : AllStatic { ...@@ -280,6 +280,9 @@ class Arguments : AllStatic {
// Option flags // Option flags
static bool _has_profile; static bool _has_profile;
static const char* _gc_log_filename; 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; static uintx _min_heap_size;
// -Xrun arguments // -Xrun arguments
...@@ -327,6 +330,7 @@ class Arguments : AllStatic { ...@@ -327,6 +330,7 @@ class Arguments : AllStatic {
// Garbage-First (UseG1GC) // Garbage-First (UseG1GC)
static void set_g1_gc_flags(); static void set_g1_gc_flags();
// GC ergonomics // GC ergonomics
static void set_conservative_max_heap_alignment();
static void set_use_compressed_oops(); static void set_use_compressed_oops();
static void set_use_compressed_klass_ptrs(); static void set_use_compressed_klass_ptrs();
static void set_ergonomics_flags(); static void set_ergonomics_flags();
...@@ -430,8 +434,10 @@ class Arguments : AllStatic { ...@@ -430,8 +434,10 @@ class Arguments : AllStatic {
static char* SharedArchivePath; static char* SharedArchivePath;
public: public:
// Parses the arguments // Parses the arguments, first phase
static jint parse(const JavaVMInitArgs* args); static jint parse(const JavaVMInitArgs* args);
// Apply ergonomics
static jint apply_ergo();
// Adjusts the arguments after the OS have adjusted the arguments // Adjusts the arguments after the OS have adjusted the arguments
static jint adjust_after_os(); static jint adjust_after_os();
// Check for consistency in the selection of the garbage collector. // Check for consistency in the selection of the garbage collector.
...@@ -445,6 +451,10 @@ class Arguments : AllStatic { ...@@ -445,6 +451,10 @@ class Arguments : AllStatic {
// Used by os_solaris // Used by os_solaris
static bool process_settings_file(const char* file_name, bool should_exist, jboolean ignore_unrecognized); 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 // return a char* array containing all options
static char** jvm_flags_array() { return _jvm_flags_array; } static char** jvm_flags_array() { return _jvm_flags_array; }
static char** jvm_args_array() { return _jvm_args_array; } static char** jvm_args_array() { return _jvm_args_array; }
......
...@@ -314,6 +314,11 @@ static void signal_thread_entry(JavaThread* thread, TRAPS) { ...@@ -314,6 +314,11 @@ static void signal_thread_entry(JavaThread* thread, TRAPS) {
} }
} }
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() { void os::signal_init() {
if (!ReduceSignalUsage) { if (!ReduceSignalUsage) {
......
...@@ -139,7 +139,10 @@ class os: AllStatic { ...@@ -139,7 +139,10 @@ class os: AllStatic {
public: public:
static void init(void); // Called before command line parsing 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 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 static void init_globals(void) { // Called from init_globals() in init.cpp
init_globals_ext(); init_globals_ext();
} }
...@@ -254,6 +257,11 @@ class os: AllStatic { ...@@ -254,6 +257,11 @@ class os: AllStatic {
static size_t page_size_for_region(size_t region_min_size, static size_t page_size_for_region(size_t region_min_size,
size_t region_max_size, size_t region_max_size,
uint min_pages); 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 // Methods for tracing page sizes returned by the above method; enabled by
// TracePageSizes. The region_{min,max}_size parameters should be the values // TracePageSizes. The region_{min,max}_size parameters should be the values
......
...@@ -3329,6 +3329,11 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) { ...@@ -3329,6 +3329,11 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) {
jint parse_result = Arguments::parse(args); jint parse_result = Arguments::parse(args);
if (parse_result != JNI_OK) return parse_result; 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) { if (PauseAtStartup) {
os::pause(); os::pause();
} }
......
/*
* 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);
}
}
/*
* 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);
}
}
...@@ -61,6 +61,8 @@ public class WhiteBox { ...@@ -61,6 +61,8 @@ public class WhiteBox {
registerNatives(); registerNatives();
} }
// Get the maximum heap size supporting COOPs
public native long getCompressedOopsMaxHeapSize();
// Arguments // Arguments
public native void printHeapSizes(); public native void printHeapSizes();
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册