8000968: NPG: UseCompressedKlassPointers asserts with ObjectAlignmentInBytes for > 32G CompressedOops
Summary: Pick a base that works for both CompressedOpps alignment and CompressedKlassPtrs alignment.
Reviewed-by: kvn, roland
--- a/hotspot/src/share/vm/memory/universe.cpp Sun Feb 03 17:12:31 2013 -0500
+++ b/hotspot/src/share/vm/memory/universe.cpp Mon Feb 04 08:26:02 2013 -0500
@@ -144,6 +144,7 @@
NarrowPtrStruct Universe::_narrow_klass = { NULL, 0, true };
address Universe::_narrow_ptrs_base;
+size_t Universe::_class_metaspace_size;
void Universe::basic_type_classes_do(void f(Klass*)) {
f(boolArrayKlassObj());
@@ -689,8 +690,15 @@
// Return specified base for the first request.
if (!FLAG_IS_DEFAULT(HeapBaseMinAddress) && (mode == UnscaledNarrowOop)) {
base = HeapBaseMinAddress;
- } else if (total_size <= OopEncodingHeapMax && (mode != HeapBasedNarrowOop)) {
- if (total_size <= NarrowOopHeapMax && (mode == UnscaledNarrowOop) &&
+
+ // If the total size and the metaspace size are small enough to allow
+ // UnscaledNarrowOop then just use UnscaledNarrowOop.
+ } else if ((total_size <= OopEncodingHeapMax) && (mode != HeapBasedNarrowOop) &&
+ (!UseCompressedKlassPointers ||
+ (((OopEncodingHeapMax - heap_size) + Universe::class_metaspace_size()) <= KlassEncodingMetaspaceMax))) {
+ // We don't need to check the metaspace size here because it is always smaller
+ // than total_size.
+ if ((total_size <= NarrowOopHeapMax) && (mode == UnscaledNarrowOop) &&
(Universe::narrow_oop_shift() == 0)) {
// Use 32-bits oops without encoding and
// place heap's top on the 4Gb boundary
@@ -706,14 +714,24 @@
base = (OopEncodingHeapMax - heap_size);
}
}
+
+ // See if ZeroBaseNarrowOop encoding will work for a heap based at
+ // (KlassEncodingMetaspaceMax - class_metaspace_size()).
+ } else if (UseCompressedKlassPointers && (mode != HeapBasedNarrowOop) &&
+ (Universe::class_metaspace_size() + HeapBaseMinAddress <= KlassEncodingMetaspaceMax) &&
+ (KlassEncodingMetaspaceMax + heap_size - Universe::class_metaspace_size() <= OopEncodingHeapMax)) {
+ base = (KlassEncodingMetaspaceMax - Universe::class_metaspace_size());
} else {
- // Can't reserve below 32Gb.
+ // UnscaledNarrowOop encoding didn't work, and no base was found for ZeroBasedOops or
+ // HeapBasedNarrowOop encoding was requested. So, can't reserve below 32Gb.
Universe::set_narrow_oop_shift(LogMinObjAlignmentInBytes);
}
+
// Set narrow_oop_base and narrow_oop_use_implicit_null_checks
// used in ReservedHeapSpace() constructors.
// The final values will be set in initialize_heap() below.
- if (base != 0 && (base + heap_size) <= OopEncodingHeapMax) {
+ if ((base != 0) && ((base + heap_size) <= OopEncodingHeapMax) &&
+ (!UseCompressedKlassPointers || (base + Universe::class_metaspace_size()) <= KlassEncodingMetaspaceMax)) {
// Use zero based compressed oops
Universe::set_narrow_oop_base(NULL);
// Don't need guard page for implicit checks in indexed
@@ -796,7 +814,9 @@
tty->print("heap address: " PTR_FORMAT ", size: " SIZE_FORMAT " MB",
Universe::heap()->base(), Universe::heap()->reserved_region().byte_size()/M);
}
- if ((uint64_t)Universe::heap()->reserved_region().end() > OopEncodingHeapMax) {
+ if (((uint64_t)Universe::heap()->reserved_region().end() > OopEncodingHeapMax) ||
+ (UseCompressedKlassPointers &&
+ ((uint64_t)Universe::heap()->base() + Universe::class_metaspace_size() > KlassEncodingMetaspaceMax))) {
// Can't reserve heap below 32Gb.
// keep the Universe::narrow_oop_base() set in Universe::reserve_heap()
Universe::set_narrow_oop_shift(LogMinObjAlignmentInBytes);
@@ -862,8 +882,8 @@
// be compressed the same as instances.
// Need to round class space size up because it's below the heap and
// the actual alignment depends on its size.
- size_t metaspace_size = align_size_up(ClassMetaspaceSize, alignment);
- size_t total_reserved = align_size_up(heap_size + metaspace_size, alignment);
+ Universe::set_class_metaspace_size(align_size_up(ClassMetaspaceSize, alignment));
+ size_t total_reserved = align_size_up(heap_size + Universe::class_metaspace_size(), alignment);
char* addr = Universe::preferred_heap_base(total_reserved, Universe::UnscaledNarrowOop);
ReservedHeapSpace total_rs(total_reserved, alignment, UseLargePages, addr);
@@ -904,8 +924,8 @@
// compressed oops is greater than the one used for compressed klass
// ptrs, a metadata space on top of the heap could become
// unreachable.
- ReservedSpace class_rs = total_rs.first_part(metaspace_size);
- ReservedSpace heap_rs = total_rs.last_part(metaspace_size, alignment);
+ ReservedSpace class_rs = total_rs.first_part(Universe::class_metaspace_size());
+ ReservedSpace heap_rs = total_rs.last_part(Universe::class_metaspace_size(), alignment);
Metaspace::initialize_class_space(class_rs);
if (UseCompressedOops) {
--- a/hotspot/src/share/vm/memory/universe.hpp Sun Feb 03 17:12:31 2013 -0500
+++ b/hotspot/src/share/vm/memory/universe.hpp Mon Feb 04 08:26:02 2013 -0500
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -211,6 +211,9 @@
static struct NarrowPtrStruct _narrow_klass;
static address _narrow_ptrs_base;
+ // Aligned size of the metaspace.
+ static size_t _class_metaspace_size;
+
// array of dummy objects used with +FullGCAlot
debug_only(static objArrayOop _fullgc_alot_dummy_array;)
// index of next entry to clear
@@ -278,6 +281,13 @@
static bool reserve_metaspace_helper(bool with_base = false);
static ReservedHeapSpace reserve_heap_metaspace(size_t heap_size, size_t alignment, bool& contiguous);
+ static size_t class_metaspace_size() {
+ return _class_metaspace_size;
+ }
+ static void set_class_metaspace_size(size_t metaspace_size) {
+ _class_metaspace_size = metaspace_size;
+ }
+
// Debugging
static int _verify_count; // number of verifies done
// True during call to verify(). Should only be set/cleared in verify().
--- a/hotspot/src/share/vm/oops/oop.inline.hpp Sun Feb 03 17:12:31 2013 -0500
+++ b/hotspot/src/share/vm/oops/oop.inline.hpp Mon Feb 04 08:26:02 2013 -0500
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -227,12 +227,12 @@
// might not be the same as oop.
inline narrowOop oopDesc::encode_klass_not_null(Klass* v) {
- assert(!is_null(v), "oop value can never be zero");
+ assert(!is_null(v), "klass value can never be zero");
assert(check_klass_alignment(v), "Address not aligned");
address base = Universe::narrow_klass_base();
int shift = Universe::narrow_klass_shift();
uint64_t pd = (uint64_t)(pointer_delta((void*)v, (void*)base, 1));
- assert(OopEncodingHeapMax > pd, "change encoding max if new encoding");
+ assert(KlassEncodingMetaspaceMax > pd, "change encoding max if new encoding");
uint64_t result = pd >> shift;
assert((result & CONST64(0xffffffff00000000)) == 0, "narrow klass pointer overflow");
assert(decode_klass(result) == v, "reversibility");
--- a/hotspot/src/share/vm/runtime/arguments.cpp Sun Feb 03 17:12:31 2013 -0500
+++ b/hotspot/src/share/vm/runtime/arguments.cpp Mon Feb 04 08:26:02 2013 -0500
@@ -1446,13 +1446,18 @@
}
// Set the ClassMetaspaceSize to something that will not need to be
// expanded, since it cannot be expanded.
- if (UseCompressedKlassPointers && FLAG_IS_DEFAULT(ClassMetaspaceSize)) {
- // 100,000 classes seems like a good size, so 100M assumes around 1K
- // per klass. The vtable and oopMap is embedded so we don't have a fixed
- // size per klass. Eventually, this will be parameterized because it
- // would also be useful to determine the optimal size of the
- // systemDictionary.
- FLAG_SET_ERGO(uintx, ClassMetaspaceSize, 100*M);
+ if (UseCompressedKlassPointers) {
+ if (ClassMetaspaceSize > KlassEncodingMetaspaceMax) {
+ warning("Class metaspace size is too large for UseCompressedKlassPointers");
+ FLAG_SET_DEFAULT(UseCompressedKlassPointers, false);
+ } else if (FLAG_IS_DEFAULT(ClassMetaspaceSize)) {
+ // 100,000 classes seems like a good size, so 100M assumes around 1K
+ // per klass. The vtable and oopMap is embedded so we don't have a fixed
+ // size per klass. Eventually, this will be parameterized because it
+ // would also be useful to determine the optimal size of the
+ // systemDictionary.
+ FLAG_SET_ERGO(uintx, ClassMetaspaceSize, 100*M);
+ }
}
}
// Also checks that certain machines are slower with compressed oops
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/8000968/Test8000968.sh Mon Feb 04 08:26:02 2013 -0500
@@ -0,0 +1,99 @@
+#
+# 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 Test8000968.sh
+# @bug 8000968
+# @summary NPG: UseCompressedKlassPointers asserts with ObjectAlignmentInBytes=32
+# @run shell Test8000968.sh
+#
+
+if [ "${TESTJAVA}" = "" ]
+then
+ PARENT=`dirname \`which java\``
+ TESTJAVA=`dirname ${PARENT}`
+ printf "TESTJAVA not set, selecting " ${TESTJAVA}
+ printf " If this is incorrect, try setting the variable manually.\n"
+fi
+
+
+# set platform-dependent variables
+OS=`uname -s`
+case "$OS" in
+ Windows_* )
+ FS="\\"
+ NULL=NUL
+ ;;
+ * )
+ FS="/"
+ NULL=/dev/null
+ ;;
+esac
+
+JAVA=${TESTJAVA}${FS}bin${FS}java
+
+#
+# See if platform has 64 bit java.
+#
+${JAVA} ${TESTVMOPTS} -d64 -version 2>&1 | grep -i "does not support" > ${NULL}
+if [ "$?" != "1" ]
+then
+ printf "Platform is 32 bit, does not support -XX:ObjectAlignmentInBytes= option.\n"
+ printf "Passed.\n"
+ exit 0
+fi
+
+#
+# Test -XX:ObjectAlignmentInBytes with -XX:+UseCompressedKlassPointers -XX:+UseCompressedOops.
+#
+${JAVA} ${TESTVMOPTS} -d64 -XX:+UseCompressedKlassPointers -XX:+UseCompressedOops -XX:ObjectAlignmentInBytes=16 -version 2>&1 > ${NULL}
+if [ "$?" != "0" ]
+then
+ printf "FAILED: -XX:ObjectAlignmentInBytes=16 option did not work.\n"
+ exit 1
+fi
+
+${JAVA} ${TESTVMOPTS} -d64 -XX:+UseCompressedKlassPointers -XX:+UseCompressedOops -XX:ObjectAlignmentInBytes=32 -version 2>&1 > ${NULL}
+if [ "$?" != "0" ]
+then
+ printf "FAILED: -XX:ObjectAlignmentInBytes=32 option did not work.\n"
+ exit 1
+fi
+
+${JAVA} ${TESTVMOPTS} -d64 -XX:+UseCompressedKlassPointers -XX:+UseCompressedOops -XX:ObjectAlignmentInBytes=64 -version 2>&1 > ${NULL}
+if [ "$?" != "0" ]
+then
+ printf "FAILED: -XX:ObjectAlignmentInBytes=64 option did not work.\n"
+ exit 1
+fi
+
+${JAVA} ${TESTVMOPTS} -d64 -XX:+UseCompressedKlassPointers -XX:+UseCompressedOops -XX:ObjectAlignmentInBytes=128 -version 2>&1 > ${NULL}
+if [ "$?" != "0" ]
+then
+ printf "FAILED: -XX:ObjectAlignmentInBytes=128 option did not work.\n"
+ exit 1
+fi
+
+
+printf "Passed.\n"
+exit 0