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

Wed, 11 Sep 2013 16:25:02 +0200

author
tschatzl
date
Wed, 11 Sep 2013 16:25:02 +0200
changeset 5701
40136aa2cdb1
parent 5698
040895ec3920
child 5702
b82260e84582

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

src/os/bsd/vm/os_bsd.cpp file | annotate | diff | comparison | revisions
src/os/linux/vm/os_linux.cpp file | annotate | diff | comparison | revisions
src/os/solaris/vm/os_solaris.cpp file | annotate | diff | comparison | revisions
src/os/windows/vm/os_windows.cpp file | annotate | diff | comparison | revisions
src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp file | annotate | diff | comparison | revisions
src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp file | annotate | diff | comparison | revisions
src/share/vm/gc_implementation/g1/heapRegion.cpp file | annotate | diff | comparison | revisions
src/share/vm/gc_implementation/g1/heapRegion.hpp file | annotate | diff | comparison | revisions
src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.hpp file | annotate | diff | comparison | revisions
src/share/vm/memory/collectorPolicy.cpp file | annotate | diff | comparison | revisions
src/share/vm/memory/collectorPolicy.hpp file | annotate | diff | comparison | revisions
src/share/vm/memory/genCollectedHeap.hpp file | annotate | diff | comparison | revisions
src/share/vm/memory/universe.cpp file | annotate | diff | comparison | revisions
src/share/vm/prims/whitebox.cpp file | annotate | diff | comparison | revisions
src/share/vm/runtime/arguments.cpp file | annotate | diff | comparison | revisions
src/share/vm/runtime/arguments.hpp file | annotate | diff | comparison | revisions
src/share/vm/runtime/os.cpp file | annotate | diff | comparison | revisions
src/share/vm/runtime/os.hpp file | annotate | diff | comparison | revisions
src/share/vm/runtime/thread.cpp file | annotate | diff | comparison | revisions
test/gc/arguments/TestUseCompressedOopsErgo.java file | annotate | diff | comparison | revisions
test/gc/arguments/TestUseCompressedOopsErgoTools.java file | annotate | diff | comparison | revisions
test/testlibrary/whitebox/sun/hotspot/WhiteBox.java file | annotate | diff | comparison | revisions
     1.1 --- a/src/os/bsd/vm/os_bsd.cpp	Wed Sep 11 12:03:41 2013 +0200
     1.2 +++ b/src/os/bsd/vm/os_bsd.cpp	Wed Sep 11 16:25:02 2013 +0200
     1.3 @@ -3589,8 +3589,6 @@
     1.4  #endif
     1.5    }
     1.6  
     1.7 -  os::large_page_init();
     1.8 -
     1.9    // initialize suspend/resume support - must do this before signal_sets_init()
    1.10    if (SR_initialize() != 0) {
    1.11      perror("SR_initialize failed");
     2.1 --- a/src/os/linux/vm/os_linux.cpp	Wed Sep 11 12:03:41 2013 +0200
     2.2 +++ b/src/os/linux/vm/os_linux.cpp	Wed Sep 11 16:25:02 2013 +0200
     2.3 @@ -4755,8 +4755,6 @@
     2.4  #endif
     2.5    }
     2.6  
     2.7 -  os::large_page_init();
     2.8 -
     2.9    // initialize suspend/resume support - must do this before signal_sets_init()
    2.10    if (SR_initialize() != 0) {
    2.11      perror("SR_initialize failed");
     3.1 --- a/src/os/solaris/vm/os_solaris.cpp	Wed Sep 11 12:03:41 2013 +0200
     3.2 +++ b/src/os/solaris/vm/os_solaris.cpp	Wed Sep 11 16:25:02 2013 +0200
     3.3 @@ -5178,9 +5178,7 @@
     3.4      if(Verbose && PrintMiscellaneous)
     3.5        tty->print("[Memory Serialize  Page address: " INTPTR_FORMAT "]\n", (intptr_t)mem_serialize_page);
     3.6  #endif
     3.7 -}
     3.8 -
     3.9 -  os::large_page_init();
    3.10 +  }
    3.11  
    3.12    // Check minimum allowable stack size for thread creation and to initialize
    3.13    // the java system classes, including StackOverflowError - depends on page
     4.1 --- a/src/os/windows/vm/os_windows.cpp	Wed Sep 11 12:03:41 2013 +0200
     4.2 +++ b/src/os/windows/vm/os_windows.cpp	Wed Sep 11 16:25:02 2013 +0200
     4.3 @@ -3920,8 +3920,6 @@
     4.4  #endif
     4.5    }
     4.6  
     4.7 -  os::large_page_init();
     4.8 -
     4.9    // Setup Windows Exceptions
    4.10  
    4.11    // for debugging float code generation bugs
     5.1 --- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp	Wed Sep 11 12:03:41 2013 +0200
     5.2 +++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp	Wed Sep 11 16:25:02 2013 +0200
     5.3 @@ -2191,6 +2191,10 @@
     5.4    return JNI_OK;
     5.5  }
     5.6  
     5.7 +size_t G1CollectedHeap::conservative_max_heap_alignment() {
     5.8 +  return HeapRegion::max_region_size();
     5.9 +}
    5.10 +
    5.11  void G1CollectedHeap::ref_processing_init() {
    5.12    // Reference processing in G1 currently works as follows:
    5.13    //
     6.1 --- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp	Wed Sep 11 12:03:41 2013 +0200
     6.2 +++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp	Wed Sep 11 16:25:02 2013 +0200
     6.3 @@ -1092,6 +1092,9 @@
     6.4    // specified by the policy object.
     6.5    jint initialize();
     6.6  
     6.7 +  // Return the (conservative) maximum heap alignment for any G1 heap
     6.8 +  static size_t conservative_max_heap_alignment();
     6.9 +
    6.10    // Initialize weak reference processing.
    6.11    virtual void ref_processing_init();
    6.12  
     7.1 --- a/src/share/vm/gc_implementation/g1/heapRegion.cpp	Wed Sep 11 12:03:41 2013 +0200
     7.2 +++ b/src/share/vm/gc_implementation/g1/heapRegion.cpp	Wed Sep 11 16:25:02 2013 +0200
     7.3 @@ -1,5 +1,5 @@
     7.4  /*
     7.5 - * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
     7.6 + * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
     7.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     7.8   *
     7.9   * This code is free software; you can redistribute it and/or modify it
    7.10 @@ -149,6 +149,10 @@
    7.11  // many regions in the heap (based on the min heap size).
    7.12  #define TARGET_REGION_NUMBER          2048
    7.13  
    7.14 +size_t HeapRegion::max_region_size() {
    7.15 +  return (size_t)MAX_REGION_SIZE;
    7.16 +}
    7.17 +
    7.18  void HeapRegion::setup_heap_region_size(size_t initial_heap_size, size_t max_heap_size) {
    7.19    uintx region_size = G1HeapRegionSize;
    7.20    if (FLAG_IS_DEFAULT(G1HeapRegionSize)) {
     8.1 --- a/src/share/vm/gc_implementation/g1/heapRegion.hpp	Wed Sep 11 12:03:41 2013 +0200
     8.2 +++ b/src/share/vm/gc_implementation/g1/heapRegion.hpp	Wed Sep 11 16:25:02 2013 +0200
     8.3 @@ -1,5 +1,5 @@
     8.4  /*
     8.5 - * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
     8.6 + * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
     8.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     8.8   *
     8.9   * This code is free software; you can redistribute it and/or modify it
    8.10 @@ -355,6 +355,8 @@
    8.11                                        ~((1 << (size_t) LogOfHRGrainBytes) - 1);
    8.12    }
    8.13  
    8.14 +  static size_t max_region_size();
    8.15 +
    8.16    // It sets up the heap region size (GrainBytes / GrainWords), as
    8.17    // well as other related fields that are based on the heap region
    8.18    // size (LogOfHRGrainBytes / LogOfHRGrainWords /
     9.1 --- a/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.hpp	Wed Sep 11 12:03:41 2013 +0200
     9.2 +++ b/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.hpp	Wed Sep 11 16:25:02 2013 +0200
     9.3 @@ -86,6 +86,11 @@
     9.4      set_alignment(_old_gen_alignment, intra_heap_alignment());
     9.5    }
     9.6  
     9.7 +  // Return the (conservative) maximum heap alignment
     9.8 +  static size_t conservative_max_heap_alignment() {
     9.9 +    return intra_heap_alignment();
    9.10 +  }
    9.11 +
    9.12    // For use by VM operations
    9.13    enum CollectionType {
    9.14      Scavenge,
    9.15 @@ -122,7 +127,7 @@
    9.16  
    9.17    // The alignment used for eden and survivors within the young gen
    9.18    // and for boundary between young gen and old gen.
    9.19 -  size_t intra_heap_alignment() const { return 64 * K * HeapWordSize; }
    9.20 +  static size_t intra_heap_alignment() { return 64 * K * HeapWordSize; }
    9.21  
    9.22    size_t capacity() const;
    9.23    size_t used() const;
    10.1 --- a/src/share/vm/memory/collectorPolicy.cpp	Wed Sep 11 12:03:41 2013 +0200
    10.2 +++ b/src/share/vm/memory/collectorPolicy.cpp	Wed Sep 11 16:25:02 2013 +0200
    10.3 @@ -145,6 +145,30 @@
    10.4    _all_soft_refs_clear = true;
    10.5  }
    10.6  
    10.7 +size_t CollectorPolicy::compute_max_alignment() {
    10.8 +  // The card marking array and the offset arrays for old generations are
    10.9 +  // committed in os pages as well. Make sure they are entirely full (to
   10.10 +  // avoid partial page problems), e.g. if 512 bytes heap corresponds to 1
   10.11 +  // byte entry and the os page size is 4096, the maximum heap size should
   10.12 +  // be 512*4096 = 2MB aligned.
   10.13 +
   10.14 +  // There is only the GenRemSet in Hotspot and only the GenRemSet::CardTable
   10.15 +  // is supported.
   10.16 +  // Requirements of any new remembered set implementations must be added here.
   10.17 +  size_t alignment = GenRemSet::max_alignment_constraint(GenRemSet::CardTable);
   10.18 +
   10.19 +  // Parallel GC does its own alignment of the generations to avoid requiring a
   10.20 +  // large page (256M on some platforms) for the permanent generation.  The
   10.21 +  // other collectors should also be updated to do their own alignment and then
   10.22 +  // this use of lcm() should be removed.
   10.23 +  if (UseLargePages && !UseParallelGC) {
   10.24 +      // in presence of large pages we have to make sure that our
   10.25 +      // alignment is large page aware
   10.26 +      alignment = lcm(os::large_page_size(), alignment);
   10.27 +  }
   10.28 +
   10.29 +  return alignment;
   10.30 +}
   10.31  
   10.32  // GenCollectorPolicy methods.
   10.33  
   10.34 @@ -175,29 +199,6 @@
   10.35                                          GCTimeRatio);
   10.36  }
   10.37  
   10.38 -size_t GenCollectorPolicy::compute_max_alignment() {
   10.39 -  // The card marking array and the offset arrays for old generations are
   10.40 -  // committed in os pages as well. Make sure they are entirely full (to
   10.41 -  // avoid partial page problems), e.g. if 512 bytes heap corresponds to 1
   10.42 -  // byte entry and the os page size is 4096, the maximum heap size should
   10.43 -  // be 512*4096 = 2MB aligned.
   10.44 -  size_t alignment = GenRemSet::max_alignment_constraint(rem_set_name());
   10.45 -
   10.46 -  // Parallel GC does its own alignment of the generations to avoid requiring a
   10.47 -  // large page (256M on some platforms) for the permanent generation.  The
   10.48 -  // other collectors should also be updated to do their own alignment and then
   10.49 -  // this use of lcm() should be removed.
   10.50 -  if (UseLargePages && !UseParallelGC) {
   10.51 -      // in presence of large pages we have to make sure that our
   10.52 -      // alignment is large page aware
   10.53 -      alignment = lcm(os::large_page_size(), alignment);
   10.54 -  }
   10.55 -
   10.56 -  assert(alignment >= min_alignment(), "Must be");
   10.57 -
   10.58 -  return alignment;
   10.59 -}
   10.60 -
   10.61  void GenCollectorPolicy::initialize_flags() {
   10.62    // All sizes must be multiples of the generation granularity.
   10.63    set_min_alignment((uintx) Generation::GenGrain);
    11.1 --- a/src/share/vm/memory/collectorPolicy.hpp	Wed Sep 11 12:03:41 2013 +0200
    11.2 +++ b/src/share/vm/memory/collectorPolicy.hpp	Wed Sep 11 16:25:02 2013 +0200
    11.3 @@ -98,6 +98,9 @@
    11.4    {}
    11.5  
    11.6   public:
    11.7 +  // Return maximum heap alignment that may be imposed by the policy
    11.8 +  static size_t compute_max_alignment();
    11.9 +
   11.10    void set_min_alignment(size_t align)         { _min_alignment = align; }
   11.11    size_t min_alignment()                       { return _min_alignment; }
   11.12    void set_max_alignment(size_t align)         { _max_alignment = align; }
   11.13 @@ -234,9 +237,6 @@
   11.14    // Try to allocate space by expanding the heap.
   11.15    virtual HeapWord* expand_heap_and_allocate(size_t size, bool is_tlab);
   11.16  
   11.17 -  // compute max heap alignment
   11.18 -  size_t compute_max_alignment();
   11.19 -
   11.20   // Scale the base_size by NewRation according to
   11.21   //     result = base_size / (NewRatio + 1)
   11.22   // and align by min_alignment()
    12.1 --- a/src/share/vm/memory/genCollectedHeap.hpp	Wed Sep 11 12:03:41 2013 +0200
    12.2 +++ b/src/share/vm/memory/genCollectedHeap.hpp	Wed Sep 11 16:25:02 2013 +0200
    12.3 @@ -1,5 +1,5 @@
    12.4  /*
    12.5 - * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
    12.6 + * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
    12.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    12.8   *
    12.9   * This code is free software; you can redistribute it and/or modify it
   12.10 @@ -148,6 +148,11 @@
   12.11      return gen_policy()->size_policy();
   12.12    }
   12.13  
   12.14 +  // Return the (conservative) maximum heap alignment
   12.15 +  static size_t conservative_max_heap_alignment() {
   12.16 +    return Generation::GenGrain;
   12.17 +  }
   12.18 +
   12.19    size_t capacity() const;
   12.20    size_t used() const;
   12.21  
    13.1 --- a/src/share/vm/memory/universe.cpp	Wed Sep 11 12:03:41 2013 +0200
    13.2 +++ b/src/share/vm/memory/universe.cpp	Wed Sep 11 16:25:02 2013 +0200
    13.3 @@ -872,6 +872,9 @@
    13.4  
    13.5  // Reserve the Java heap, which is now the same for all GCs.
    13.6  ReservedSpace Universe::reserve_heap(size_t heap_size, size_t alignment) {
    13.7 +  assert(alignment <= Arguments::conservative_max_heap_alignment(),
    13.8 +      err_msg("actual alignment "SIZE_FORMAT" must be within maximum heap alignment "SIZE_FORMAT,
    13.9 +          alignment, Arguments::conservative_max_heap_alignment()));
   13.10    size_t total_reserved = align_size_up(heap_size, alignment);
   13.11    assert(!UseCompressedOops || (total_reserved <= (OopEncodingHeapMax - os::vm_page_size())),
   13.12        "heap size is too big for compressed oops");
    14.1 --- a/src/share/vm/prims/whitebox.cpp	Wed Sep 11 12:03:41 2013 +0200
    14.2 +++ b/src/share/vm/prims/whitebox.cpp	Wed Sep 11 16:25:02 2013 +0200
    14.3 @@ -33,6 +33,7 @@
    14.4  #include "prims/whitebox.hpp"
    14.5  #include "prims/wbtestmethods/parserTests.hpp"
    14.6  
    14.7 +#include "runtime/arguments.hpp"
    14.8  #include "runtime/interfaceSupport.hpp"
    14.9  #include "runtime/os.hpp"
   14.10  #include "utilities/debug.hpp"
   14.11 @@ -94,6 +95,11 @@
   14.12    return closure.found();
   14.13  WB_END
   14.14  
   14.15 +WB_ENTRY(jlong, WB_GetCompressedOopsMaxHeapSize(JNIEnv* env, jobject o)) {
   14.16 +  return (jlong)Arguments::max_heap_for_compressed_oops();
   14.17 +}
   14.18 +WB_END
   14.19 +
   14.20  WB_ENTRY(void, WB_PrintHeapSizes(JNIEnv* env, jobject o)) {
   14.21    CollectorPolicy * p = Universe::heap()->collector_policy();
   14.22    gclog_or_tty->print_cr("Minimum heap "SIZE_FORMAT" Initial heap "
   14.23 @@ -436,6 +442,8 @@
   14.24        CC"(Ljava/lang/String;[Lsun/hotspot/parser/DiagnosticCommand;)[Ljava/lang/Object;",
   14.25        (void*) &WB_ParseCommandLine
   14.26    },
   14.27 +  {CC"getCompressedOopsMaxHeapSize", CC"()J",
   14.28 +      (void*)&WB_GetCompressedOopsMaxHeapSize},
   14.29    {CC"printHeapSizes",     CC"()V",                   (void*)&WB_PrintHeapSizes    },
   14.30  #if INCLUDE_ALL_GCS
   14.31    {CC"g1InConcurrentMark", CC"()Z",                   (void*)&WB_G1InConcurrentMark},
    15.1 --- a/src/share/vm/runtime/arguments.cpp	Wed Sep 11 12:03:41 2013 +0200
    15.2 +++ b/src/share/vm/runtime/arguments.cpp	Wed Sep 11 16:25:02 2013 +0200
    15.3 @@ -28,6 +28,7 @@
    15.4  #include "compiler/compilerOracle.hpp"
    15.5  #include "memory/allocation.inline.hpp"
    15.6  #include "memory/cardTableRS.hpp"
    15.7 +#include "memory/genCollectedHeap.hpp"
    15.8  #include "memory/referenceProcessor.hpp"
    15.9  #include "memory/universe.inline.hpp"
   15.10  #include "oops/oop.inline.hpp"
   15.11 @@ -54,6 +55,8 @@
   15.12  #endif
   15.13  #if INCLUDE_ALL_GCS
   15.14  #include "gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp"
   15.15 +#include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
   15.16 +#include "gc_implementation/parallelScavenge/parallelScavengeHeap.hpp"
   15.17  #endif // INCLUDE_ALL_GCS
   15.18  
   15.19  // Note: This is a special bug reporting site for the JVM
   15.20 @@ -90,6 +93,7 @@
   15.21  SystemProperty* Arguments::_system_properties   = NULL;
   15.22  const char*  Arguments::_gc_log_filename        = NULL;
   15.23  bool   Arguments::_has_profile                  = false;
   15.24 +size_t Arguments::_conservative_max_heap_alignment = 0;
   15.25  uintx  Arguments::_min_heap_size                = 0;
   15.26  Arguments::Mode Arguments::_mode                = _mixed;
   15.27  bool   Arguments::_java_compiler                = false;
   15.28 @@ -1391,10 +1395,17 @@
   15.29    return true;
   15.30  }
   15.31  
   15.32 -inline uintx max_heap_for_compressed_oops() {
   15.33 +uintx Arguments::max_heap_for_compressed_oops() {
   15.34    // Avoid sign flip.
   15.35    assert(OopEncodingHeapMax > (uint64_t)os::vm_page_size(), "Unusual page size");
   15.36 -  LP64_ONLY(return OopEncodingHeapMax - os::vm_page_size());
   15.37 +  // We need to fit both the NULL page and the heap into the memory budget, while
   15.38 +  // keeping alignment constraints of the heap. To guarantee the latter, as the
   15.39 +  // NULL page is located before the heap, we pad the NULL page to the conservative
   15.40 +  // maximum alignment that the GC may ever impose upon the heap.
   15.41 +  size_t displacement_due_to_null_page = align_size_up_(os::vm_page_size(),
   15.42 +    Arguments::conservative_max_heap_alignment());
   15.43 +
   15.44 +  LP64_ONLY(return OopEncodingHeapMax - displacement_due_to_null_page);
   15.45    NOT_LP64(ShouldNotReachHere(); return 0);
   15.46  }
   15.47  
   15.48 @@ -1475,6 +1486,23 @@
   15.49  #endif // !ZERO
   15.50  }
   15.51  
   15.52 +void Arguments::set_conservative_max_heap_alignment() {
   15.53 +  // The conservative maximum required alignment for the heap is the maximum of
   15.54 +  // the alignments imposed by several sources: any requirements from the heap
   15.55 +  // itself, the collector policy and the maximum page size we may run the VM
   15.56 +  // with.
   15.57 +  size_t heap_alignment = GenCollectedHeap::conservative_max_heap_alignment();
   15.58 +#if INCLUDE_ALL_GCS
   15.59 +  if (UseParallelGC) {
   15.60 +    heap_alignment = ParallelScavengeHeap::conservative_max_heap_alignment();
   15.61 +  } else if (UseG1GC) {
   15.62 +    heap_alignment = G1CollectedHeap::conservative_max_heap_alignment();
   15.63 +  }
   15.64 +#endif // INCLUDE_ALL_GCS
   15.65 +  _conservative_max_heap_alignment = MAX3(heap_alignment, os::max_page_size(),
   15.66 +    CollectorPolicy::compute_max_alignment());
   15.67 +}
   15.68 +
   15.69  void Arguments::set_ergonomics_flags() {
   15.70  
   15.71    if (os::is_server_class_machine()) {
   15.72 @@ -1503,6 +1531,8 @@
   15.73      }
   15.74    }
   15.75  
   15.76 +  set_conservative_max_heap_alignment();
   15.77 +
   15.78  #ifndef ZERO
   15.79  #ifdef _LP64
   15.80    set_use_compressed_oops();
   15.81 @@ -3506,6 +3536,11 @@
   15.82    no_shared_spaces();
   15.83  #endif // INCLUDE_CDS
   15.84  
   15.85 +  return JNI_OK;
   15.86 +}
   15.87 +
   15.88 +jint Arguments::apply_ergo() {
   15.89 +
   15.90    // Set flags based on ergonomics.
   15.91    set_ergonomics_flags();
   15.92  
    16.1 --- a/src/share/vm/runtime/arguments.hpp	Wed Sep 11 12:03:41 2013 +0200
    16.2 +++ b/src/share/vm/runtime/arguments.hpp	Wed Sep 11 16:25:02 2013 +0200
    16.3 @@ -280,6 +280,9 @@
    16.4    // Option flags
    16.5    static bool   _has_profile;
    16.6    static const char*  _gc_log_filename;
    16.7 +  // Value of the conservative maximum heap alignment needed
    16.8 +  static size_t  _conservative_max_heap_alignment;
    16.9 +
   16.10    static uintx  _min_heap_size;
   16.11  
   16.12    // -Xrun arguments
   16.13 @@ -327,6 +330,7 @@
   16.14    // Garbage-First (UseG1GC)
   16.15    static void set_g1_gc_flags();
   16.16    // GC ergonomics
   16.17 +  static void set_conservative_max_heap_alignment();
   16.18    static void set_use_compressed_oops();
   16.19    static void set_use_compressed_klass_ptrs();
   16.20    static void set_ergonomics_flags();
   16.21 @@ -430,8 +434,10 @@
   16.22    static char*  SharedArchivePath;
   16.23  
   16.24   public:
   16.25 -  // Parses the arguments
   16.26 +  // Parses the arguments, first phase
   16.27    static jint parse(const JavaVMInitArgs* args);
   16.28 +  // Apply ergonomics
   16.29 +  static jint apply_ergo();
   16.30    // Adjusts the arguments after the OS have adjusted the arguments
   16.31    static jint adjust_after_os();
   16.32    // Check for consistency in the selection of the garbage collector.
   16.33 @@ -445,6 +451,10 @@
   16.34    // Used by os_solaris
   16.35    static bool process_settings_file(const char* file_name, bool should_exist, jboolean ignore_unrecognized);
   16.36  
   16.37 +  static size_t conservative_max_heap_alignment() { return _conservative_max_heap_alignment; }
   16.38 +  // Return the maximum size a heap with compressed oops can take
   16.39 +  static size_t max_heap_for_compressed_oops();
   16.40 +
   16.41    // return a char* array containing all options
   16.42    static char** jvm_flags_array()          { return _jvm_flags_array; }
   16.43    static char** jvm_args_array()           { return _jvm_args_array; }
    17.1 --- a/src/share/vm/runtime/os.cpp	Wed Sep 11 12:03:41 2013 +0200
    17.2 +++ b/src/share/vm/runtime/os.cpp	Wed Sep 11 16:25:02 2013 +0200
    17.3 @@ -314,6 +314,11 @@
    17.4    }
    17.5  }
    17.6  
    17.7 +void os::init_before_ergo() {
    17.8 +  // We need to initialize large page support here because ergonomics takes some
    17.9 +  // decisions depending on large page support and the calculated large page size.
   17.10 +  large_page_init();
   17.11 +}
   17.12  
   17.13  void os::signal_init() {
   17.14    if (!ReduceSignalUsage) {
    18.1 --- a/src/share/vm/runtime/os.hpp	Wed Sep 11 12:03:41 2013 +0200
    18.2 +++ b/src/share/vm/runtime/os.hpp	Wed Sep 11 16:25:02 2013 +0200
    18.3 @@ -139,7 +139,10 @@
    18.4  
    18.5   public:
    18.6    static void init(void);                      // Called before command line parsing
    18.7 +  static void init_before_ergo(void);          // Called after command line parsing
    18.8 +                                               // before VM ergonomics processing.
    18.9    static jint init_2(void);                    // Called after command line parsing
   18.10 +                                               // and VM ergonomics processing
   18.11    static void init_globals(void) {             // Called from init_globals() in init.cpp
   18.12      init_globals_ext();
   18.13    }
   18.14 @@ -254,6 +257,11 @@
   18.15    static size_t page_size_for_region(size_t region_min_size,
   18.16                                       size_t region_max_size,
   18.17                                       uint min_pages);
   18.18 +  // Return the largest page size that can be used
   18.19 +  static size_t max_page_size() {
   18.20 +    // The _page_sizes array is sorted in descending order.
   18.21 +    return _page_sizes[0];
   18.22 +  }
   18.23  
   18.24    // Methods for tracing page sizes returned by the above method; enabled by
   18.25    // TracePageSizes.  The region_{min,max}_size parameters should be the values
    19.1 --- a/src/share/vm/runtime/thread.cpp	Wed Sep 11 12:03:41 2013 +0200
    19.2 +++ b/src/share/vm/runtime/thread.cpp	Wed Sep 11 16:25:02 2013 +0200
    19.3 @@ -3329,6 +3329,11 @@
    19.4    jint parse_result = Arguments::parse(args);
    19.5    if (parse_result != JNI_OK) return parse_result;
    19.6  
    19.7 +  os::init_before_ergo();
    19.8 +
    19.9 +  jint ergo_result = Arguments::apply_ergo();
   19.10 +  if (ergo_result != JNI_OK) return ergo_result;
   19.11 +
   19.12    if (PauseAtStartup) {
   19.13      os::pause();
   19.14    }
    20.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    20.2 +++ b/test/gc/arguments/TestUseCompressedOopsErgo.java	Wed Sep 11 16:25:02 2013 +0200
    20.3 @@ -0,0 +1,50 @@
    20.4 +/*
    20.5 +* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
    20.6 +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    20.7 +*
    20.8 +* This code is free software; you can redistribute it and/or modify it
    20.9 +* under the terms of the GNU General Public License version 2 only, as
   20.10 +* published by the Free Software Foundation.
   20.11 +*
   20.12 +* This code is distributed in the hope that it will be useful, but WITHOUT
   20.13 +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   20.14 +* FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   20.15 +* version 2 for more details (a copy is included in the LICENSE file that
   20.16 +* accompanied this code).
   20.17 +*
   20.18 +* You should have received a copy of the GNU General Public License version
   20.19 +* 2 along with this work; if not, write to the Free Software Foundation,
   20.20 +* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   20.21 +*
   20.22 +* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   20.23 +* or visit www.oracle.com if you need additional information or have any
   20.24 +* questions.
   20.25 +*/
   20.26 +
   20.27 +/*
   20.28 + * @test TestUseCompressedOopsErgo
   20.29 + * @key gc
   20.30 + * @bug 8010722
   20.31 + * @summary Tests ergonomics for UseCompressedOops.
   20.32 + * @library /testlibrary /testlibrary/whitebox
   20.33 + * @build TestUseCompressedOopsErgo TestUseCompressedOopsErgoTools
   20.34 + * @run main ClassFileInstaller sun.hotspot.WhiteBox
   20.35 + * @run main/othervm TestUseCompressedOopsErgo -XX:+UseG1GC
   20.36 + * @run main/othervm TestUseCompressedOopsErgo -XX:+UseParallelGC
   20.37 + * @run main/othervm TestUseCompressedOopsErgo -XX:+UseParallelGC -XX:-UseParallelOldGC
   20.38 + * @run main/othervm TestUseCompressedOopsErgo -XX:+UseConcMarkSweepGC
   20.39 + * @run main/othervm TestUseCompressedOopsErgo -XX:+UseSerialGC
   20.40 + */
   20.41 +
   20.42 +public class TestUseCompressedOopsErgo {
   20.43 +
   20.44 +  public static void main(String args[]) throws Exception {
   20.45 +    if (!TestUseCompressedOopsErgoTools.is64bitVM()) {
   20.46 +      // this test is relevant for 64 bit VMs only
   20.47 +      return;
   20.48 +    }
   20.49 +    final String[] gcFlags = args;
   20.50 +    TestUseCompressedOopsErgoTools.checkCompressedOopsErgo(gcFlags);
   20.51 +  }
   20.52 +}
   20.53 +
    21.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    21.2 +++ b/test/gc/arguments/TestUseCompressedOopsErgoTools.java	Wed Sep 11 16:25:02 2013 +0200
    21.3 @@ -0,0 +1,179 @@
    21.4 +/*
    21.5 +* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
    21.6 +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    21.7 +*
    21.8 +* This code is free software; you can redistribute it and/or modify it
    21.9 +* under the terms of the GNU General Public License version 2 only, as
   21.10 +* published by the Free Software Foundation.
   21.11 +*
   21.12 +* This code is distributed in the hope that it will be useful, but WITHOUT
   21.13 +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   21.14 +* FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   21.15 +* version 2 for more details (a copy is included in the LICENSE file that
   21.16 +* accompanied this code).
   21.17 +*
   21.18 +* You should have received a copy of the GNU General Public License version
   21.19 +* 2 along with this work; if not, write to the Free Software Foundation,
   21.20 +* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   21.21 +*
   21.22 +* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   21.23 +* or visit www.oracle.com if you need additional information or have any
   21.24 +* questions.
   21.25 +*/
   21.26 +
   21.27 +import sun.management.ManagementFactoryHelper;
   21.28 +import com.sun.management.HotSpotDiagnosticMXBean;
   21.29 +import com.sun.management.VMOption;
   21.30 +
   21.31 +import java.util.regex.Matcher;
   21.32 +import java.util.regex.Pattern;
   21.33 +import java.util.ArrayList;
   21.34 +import java.util.Arrays;
   21.35 +
   21.36 +import com.oracle.java.testlibrary.*;
   21.37 +import sun.hotspot.WhiteBox;
   21.38 +
   21.39 +class DetermineMaxHeapForCompressedOops {
   21.40 +  public static void main(String[] args) throws Exception {
   21.41 +    WhiteBox wb = WhiteBox.getWhiteBox();
   21.42 +    System.out.print(wb.getCompressedOopsMaxHeapSize());
   21.43 +  }
   21.44 +}
   21.45 +
   21.46 +class TestUseCompressedOopsErgoTools {
   21.47 +
   21.48 +  private static long getClassMetaspaceSize() {
   21.49 +    HotSpotDiagnosticMXBean diagnostic = ManagementFactoryHelper.getDiagnosticMXBean();
   21.50 +
   21.51 +    VMOption option = diagnostic.getVMOption("ClassMetaspaceSize");
   21.52 +    return Long.parseLong(option.getValue());
   21.53 +  }
   21.54 +
   21.55 +
   21.56 +  public static long getMaxHeapForCompressedOops(String[] vmargs) throws Exception {
   21.57 +    OutputAnalyzer output = runWhiteBoxTest(vmargs, DetermineMaxHeapForCompressedOops.class.getName(), new String[] {}, false);
   21.58 +    return Long.parseLong(output.getStdout());
   21.59 +  }
   21.60 +
   21.61 +  public static boolean is64bitVM() {
   21.62 +    String val = System.getProperty("sun.arch.data.model");
   21.63 +    if (val == null) {
   21.64 +      throw new RuntimeException("Could not read sun.arch.data.model");
   21.65 +    }
   21.66 +    if (val.equals("64")) {
   21.67 +      return true;
   21.68 +    } else if (val.equals("32")) {
   21.69 +      return false;
   21.70 +    }
   21.71 +    throw new RuntimeException("Unexpected value " + val + " of sun.arch.data.model");
   21.72 +  }
   21.73 +
   21.74 +  /**
   21.75 +   * Executes a new VM process with the given class and parameters.
   21.76 +   * @param vmargs Arguments to the VM to run
   21.77 +   * @param classname Name of the class to run
   21.78 +   * @param arguments Arguments to the class
   21.79 +   * @param useTestDotJavaDotOpts Use test.java.opts as part of the VM argument string
   21.80 +   * @return The OutputAnalyzer with the results for the invocation.
   21.81 +   */
   21.82 +  public static OutputAnalyzer runWhiteBoxTest(String[] vmargs, String classname, String[] arguments, boolean useTestDotJavaDotOpts) throws Exception {
   21.83 +    ArrayList<String> finalargs = new ArrayList<String>();
   21.84 +
   21.85 +    String[] whiteboxOpts = new String[] {
   21.86 +      "-Xbootclasspath/a:.",
   21.87 +      "-XX:+UnlockDiagnosticVMOptions", "-XX:+WhiteBoxAPI",
   21.88 +      "-cp", System.getProperty("java.class.path"),
   21.89 +    };
   21.90 +
   21.91 +    if (useTestDotJavaDotOpts) {
   21.92 +      // System.getProperty("test.java.opts") is '' if no options is set,
   21.93 +      // we need to skip such a result
   21.94 +      String[] externalVMOpts = new String[0];
   21.95 +      if (System.getProperty("test.java.opts") != null && System.getProperty("test.java.opts").length() != 0) {
   21.96 +        externalVMOpts = System.getProperty("test.java.opts").split(" ");
   21.97 +      }
   21.98 +      finalargs.addAll(Arrays.asList(externalVMOpts));
   21.99 +    }
  21.100 +
  21.101 +    finalargs.addAll(Arrays.asList(vmargs));
  21.102 +    finalargs.addAll(Arrays.asList(whiteboxOpts));
  21.103 +    finalargs.add(classname);
  21.104 +    finalargs.addAll(Arrays.asList(arguments));
  21.105 +
  21.106 +    ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(finalargs.toArray(new String[0]));
  21.107 +    OutputAnalyzer output = new OutputAnalyzer(pb.start());
  21.108 +    output.shouldHaveExitValue(0);
  21.109 +    return output;
  21.110 +  }
  21.111 +
  21.112 +  private static String[] join(String[] part1, String part2) {
  21.113 +    ArrayList<String> result = new ArrayList<String>();
  21.114 +    result.addAll(Arrays.asList(part1));
  21.115 +    result.add(part2);
  21.116 +    return result.toArray(new String[0]);
  21.117 +  }
  21.118 +
  21.119 +  public static void checkCompressedOopsErgo(String[] gcflags) throws Exception {
  21.120 +    long maxHeapForCompressedOops = getMaxHeapForCompressedOops(gcflags);
  21.121 +
  21.122 +    checkUseCompressedOops(gcflags, maxHeapForCompressedOops, true);
  21.123 +    checkUseCompressedOops(gcflags, maxHeapForCompressedOops - 1, true);
  21.124 +    checkUseCompressedOops(gcflags, maxHeapForCompressedOops + 1, false);
  21.125 +
  21.126 +    // the use of HeapBaseMinAddress should not change the outcome
  21.127 +    checkUseCompressedOops(join(gcflags, "-XX:HeapBaseMinAddress=32G"), maxHeapForCompressedOops, true);
  21.128 +    checkUseCompressedOops(join(gcflags, "-XX:HeapBaseMinAddress=32G"), maxHeapForCompressedOops - 1, true);
  21.129 +    checkUseCompressedOops(join(gcflags, "-XX:HeapBaseMinAddress=32G"), maxHeapForCompressedOops + 1, false);
  21.130 +
  21.131 +    // use a different object alignment
  21.132 +    maxHeapForCompressedOops = getMaxHeapForCompressedOops(join(gcflags, "-XX:ObjectAlignmentInBytes=16"));
  21.133 +
  21.134 +    checkUseCompressedOops(join(gcflags, "-XX:ObjectAlignmentInBytes=16"), maxHeapForCompressedOops, true);
  21.135 +    checkUseCompressedOops(join(gcflags, "-XX:ObjectAlignmentInBytes=16"), maxHeapForCompressedOops - 1, true);
  21.136 +    checkUseCompressedOops(join(gcflags, "-XX:ObjectAlignmentInBytes=16"), maxHeapForCompressedOops + 1, false);
  21.137 +
  21.138 +    // use a different ClassMetaspaceSize
  21.139 +    String classMetaspaceSizeArg = "-XX:ClassMetaspaceSize=" + 2 * getClassMetaspaceSize();
  21.140 +    maxHeapForCompressedOops = getMaxHeapForCompressedOops(join(gcflags, classMetaspaceSizeArg));
  21.141 +
  21.142 +    checkUseCompressedOops(join(gcflags, classMetaspaceSizeArg), maxHeapForCompressedOops, true);
  21.143 +    checkUseCompressedOops(join(gcflags, classMetaspaceSizeArg), maxHeapForCompressedOops - 1, true);
  21.144 +    checkUseCompressedOops(join(gcflags, classMetaspaceSizeArg), maxHeapForCompressedOops + 1, false);
  21.145 +  }
  21.146 +
  21.147 +  private static void checkUseCompressedOops(String[] args, long heapsize, boolean expectUseCompressedOops) throws Exception {
  21.148 +     ArrayList<String> finalargs = new ArrayList<String>();
  21.149 +     finalargs.addAll(Arrays.asList(args));
  21.150 +     finalargs.add("-Xmx" + heapsize);
  21.151 +     finalargs.add("-XX:+PrintFlagsFinal");
  21.152 +     finalargs.add("-version");
  21.153 +
  21.154 +     String output = expectValid(finalargs.toArray(new String[0]));
  21.155 +
  21.156 +     boolean actualUseCompressedOops = getFlagBoolValue(" UseCompressedOops", output);
  21.157 +
  21.158 +     if (expectUseCompressedOops != actualUseCompressedOops) {
  21.159 +       throw new RuntimeException("Expected use of compressed oops: " + expectUseCompressedOops + " but was: " + actualUseCompressedOops);
  21.160 +     }
  21.161 +  }
  21.162 +
  21.163 +  private static boolean getFlagBoolValue(String flag, String where) {
  21.164 +    Matcher m = Pattern.compile(flag + "\\s+:?= (true|false)").matcher(where);
  21.165 +    if (!m.find()) {
  21.166 +      throw new RuntimeException("Could not find value for flag " + flag + " in output string");
  21.167 +    }
  21.168 +    String match = m.group(1).equals("true");
  21.169 +  }
  21.170 +
  21.171 +  private static String expect(String[] flags, boolean hasWarning, boolean hasError, int errorcode) throws Exception {
  21.172 +    ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(flags);
  21.173 +    OutputAnalyzer output = new OutputAnalyzer(pb.start());
  21.174 +    output.shouldHaveExitValue(errorcode);
  21.175 +    return output.getStdout();
  21.176 +  }
  21.177 +
  21.178 +  private static String expectValid(String[] flags) throws Exception {
  21.179 +    return expect(flags, false, false, 0);
  21.180 +  }
  21.181 +}
  21.182 +
    22.1 --- a/test/testlibrary/whitebox/sun/hotspot/WhiteBox.java	Wed Sep 11 12:03:41 2013 +0200
    22.2 +++ b/test/testlibrary/whitebox/sun/hotspot/WhiteBox.java	Wed Sep 11 16:25:02 2013 +0200
    22.3 @@ -61,6 +61,8 @@
    22.4      registerNatives();
    22.5    }
    22.6  
    22.7 +  // Get the maximum heap size supporting COOPs
    22.8 +  public native long getCompressedOopsMaxHeapSize();
    22.9    // Arguments
   22.10    public native void printHeapSizes();
   22.11  

mercurial