Mercurial > hg > aarch64-jdk8u51-b16-hotspot
changeset 7808:b280f4f4f119 jdk8u40-b12-aarch64
Merge to jdk8u40-b12
line wrap: on
line diff
--- a/.hgtags Fri Oct 31 21:04:37 2014 +0000 +++ b/.hgtags Tue Nov 04 17:16:46 2014 +0000 @@ -531,3 +531,28 @@ 5c1b5be2c69bcae610a790e9438da446c61d3361 hs25.40-b12 905a16825d2931345a7d6dba9e427f98eb51761a jdk8u40-b08 d96716f6cbba9f000dfb1da39d2b81264f4cdea7 hs25.40-b13 +7ff8d51e0d8fc71f3ad31fd15817083341416ca8 jdk8u40-b09 +e193bbae24effeaf476f688d8d840787db53d74e hs25.40-b14 +a4d44dfb7d30eea54bc172e4429a655454ae0bbf jdk8u25-b00 +9a2152fbd929b0d8b2f5c326a5526214ae71731a jdk8u25-b01 +d3d5604ea0dea3812e87ba76ac199d0a8be6f49f jdk8u25-b02 +27348de6239bb527c37c0bf59e938ed127b619a7 jdk8u25-b03 +220eefb3609e250a0bb0ed26236c1213b8000050 jdk8u25-b04 +db8383148bc9417dd4c38fa4cea39510f17325f3 jdk8u25-b05 +605df8463453628df49351fa63632666f18698cd jdk8u25-b06 +520188d4bade17dbe75163d1f635c08168ea560c jdk8u25-b07 +f3f50c4f9ea5d3af40cb794b6f3f2a337c8873db jdk8u25-b08 +4f209b7a580c78bac255e69f4724c42584c32a7d jdk8u25-b09 +19c692f1e4c571a9285e33e7d3d15948769fcbdd jdk8u25-b10 +9e2bb00a81910776d5b16c49a3f4c5264ceab522 jdk8u25-b11 +2993491d47df8c4b096ea7fa534162bde8b53dcf jdk8u25-b12 +ca6d25be853b5c428c6228871316671843264666 jdk8u25-b13 +c77d5db189422e2eef0443ee212644e497113b18 jdk8u25-b14 +e62c06b887310b5bd23be9b817a9a6f0daf0d0e1 jdk8u25-b15 +6467bdd4d22d8b140844dc847c43b9ba7cb0bbd1 jdk8u25-b16 +28b50d07f6f8c5a567b6a25e95a423948114a004 jdk8u25-b17 +639abc668bfe995dba811dd35411b9ea8a9041cd jdk8u25-b18 +1b3abbeee961dee49780c0e4af5337feb918c555 jdk8u40-b10 +f10fe402dfb1543723b4b117a7cba3ea3d4159f1 hs25.40-b15 +99372b2fee0eb8b3452f47230e84aa6e97003184 jdk8u40-b11 +8b9ec2da541a74ac698560b6a2bc45fccb789919 hs25.40-b16
--- a/make/bsd/makefiles/mapfile-vers-debug Fri Oct 31 21:04:37 2014 +0000 +++ b/make/bsd/makefiles/mapfile-vers-debug Tue Nov 04 17:16:46 2014 +0000 @@ -1,5 +1,5 @@ # -# Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2002, 2014, 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 @@ -82,6 +82,7 @@ _JVM_EnableCompiler _JVM_Exit _JVM_FillInStackTrace + _JVM_FindClassFromCaller _JVM_FindClassFromClass _JVM_FindClassFromClassLoader _JVM_FindClassFromBootLoader
--- a/make/bsd/makefiles/mapfile-vers-product Fri Oct 31 21:04:37 2014 +0000 +++ b/make/bsd/makefiles/mapfile-vers-product Tue Nov 04 17:16:46 2014 +0000 @@ -1,5 +1,5 @@ # -# Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2002, 2014, 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 @@ -82,6 +82,7 @@ _JVM_EnableCompiler _JVM_Exit _JVM_FillInStackTrace + _JVM_FindClassFromCaller _JVM_FindClassFromClass _JVM_FindClassFromClassLoader _JVM_FindClassFromBootLoader
--- a/make/excludeSrc.make Fri Oct 31 21:04:37 2014 +0000 +++ b/make/excludeSrc.make Tue Nov 04 17:16:46 2014 +0000 @@ -97,6 +97,7 @@ ageTable.cpp \ collectorCounters.cpp \ cSpaceCounters.cpp \ + gcId.cpp \ gcPolicyCounters.cpp \ gcStats.cpp \ gcTimer.cpp \
--- a/make/hotspot_version Fri Oct 31 21:04:37 2014 +0000 +++ b/make/hotspot_version Tue Nov 04 17:16:46 2014 +0000 @@ -35,7 +35,7 @@ HS_MAJOR_VER=25 HS_MINOR_VER=40 -HS_BUILD_NUMBER=13 +HS_BUILD_NUMBER=16 JDK_MAJOR_VER=1 JDK_MINOR_VER=8
--- a/make/jprt.properties Fri Oct 31 21:04:37 2014 +0000 +++ b/make/jprt.properties Tue Nov 04 17:16:46 2014 +0000 @@ -374,21 +374,25 @@ ${jprt.my.windows.i586}-fastdebug-c2-internalvmtests, \ ${jprt.my.windows.x64}-fastdebug-c2-internalvmtests -jprt.make.rule.test.targets.standard.wbapi = \ - ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-wbapitest, \ - ${jprt.my.solaris.x64}-{product|fastdebug}-c2-wbapitest, \ - ${jprt.my.linux.i586}-{product|fastdebug}-c2-wbapitest, \ - ${jprt.my.linux.x64}-{product|fastdebug}-c2-wbapitest, \ - ${jprt.my.windows.i586}-{product|fastdebug}-c2-wbapitest, \ - ${jprt.my.windows.x64}-{product|fastdebug}-c2-wbapitest, \ - ${jprt.my.linux.i586}-{product|fastdebug}-c1-wbapitest, \ - ${jprt.my.windows.i586}-{product|fastdebug}-c1-wbapitest +jprt.make.rule.test.targets.standard.reg.group = \ + ${jprt.my.solaris.sparcv9}-{product|fastdebug}-c2-GROUP, \ + ${jprt.my.solaris.x64}-{product|fastdebug}-c2-GROUP, \ + ${jprt.my.linux.i586}-{product|fastdebug}-c2-GROUP, \ + ${jprt.my.linux.x64}-{product|fastdebug}-c2-GROUP, \ + ${jprt.my.windows.i586}-{product|fastdebug}-c2-GROUP, \ + ${jprt.my.windows.x64}-{product|fastdebug}-c2-GROUP, \ + ${jprt.my.linux.i586}-{product|fastdebug}-c1-GROUP, \ + ${jprt.my.windows.i586}-{product|fastdebug}-c1-GROUP jprt.make.rule.test.targets.standard = \ ${jprt.make.rule.test.targets.standard.client}, \ ${jprt.make.rule.test.targets.standard.server}, \ ${jprt.make.rule.test.targets.standard.internalvmtests}, \ - ${jprt.make.rule.test.targets.standard.wbapi} + ${jprt.make.rule.test.targets.standard.reg.group:GROUP=hotspot_wbapitest}, \ + ${jprt.make.rule.test.targets.standard.reg.group:GROUP=hotspot_compiler}, \ + ${jprt.make.rule.test.targets.standard.reg.group:GROUP=hotspot_gc}, \ + ${jprt.make.rule.test.targets.standard.reg.group:GROUP=hotspot_runtime}, \ + ${jprt.make.rule.test.targets.standard.reg.group:GROUP=hotspot_serviceability} jprt.make.rule.test.targets.embedded = \ ${jprt.make.rule.test.targets.standard.client}
--- a/make/linux/makefiles/mapfile-vers-debug Fri Oct 31 21:04:37 2014 +0000 +++ b/make/linux/makefiles/mapfile-vers-debug Tue Nov 04 17:16:46 2014 +0000 @@ -1,5 +1,5 @@ # -# Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2002, 2014, 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 @@ -84,6 +84,7 @@ JVM_EnableCompiler; JVM_Exit; JVM_FillInStackTrace; + JVM_FindClassFromCaller; JVM_FindClassFromClass; JVM_FindClassFromClassLoader; JVM_FindClassFromBootLoader;
--- a/make/linux/makefiles/mapfile-vers-product Fri Oct 31 21:04:37 2014 +0000 +++ b/make/linux/makefiles/mapfile-vers-product Tue Nov 04 17:16:46 2014 +0000 @@ -1,5 +1,5 @@ # -# Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2002, 2014, 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 @@ -84,6 +84,7 @@ JVM_EnableCompiler; JVM_Exit; JVM_FillInStackTrace; + JVM_FindClassFromCaller; JVM_FindClassFromClass; JVM_FindClassFromClassLoader; JVM_FindClassFromBootLoader;
--- a/make/solaris/makefiles/mapfile-vers Fri Oct 31 21:04:37 2014 +0000 +++ b/make/solaris/makefiles/mapfile-vers Tue Nov 04 17:16:46 2014 +0000 @@ -1,5 +1,5 @@ # -# Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2000, 2014, 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 @@ -84,6 +84,7 @@ JVM_EnableCompiler; JVM_Exit; JVM_FillInStackTrace; + JVM_FindClassFromCaller; JVM_FindClassFromClass; JVM_FindClassFromClassLoader; JVM_FindClassFromBootLoader;
--- a/make/windows/makefiles/projectcreator.make Fri Oct 31 21:04:37 2014 +0000 +++ b/make/windows/makefiles/projectcreator.make Tue Nov 04 17:16:46 2014 +0000 @@ -72,6 +72,7 @@ -ignorePath arm \ -ignorePath ppc \ -ignorePath zero \ + -ignorePath aix \ -hidePath .hg
--- a/src/cpu/x86/vm/vm_version_x86.cpp Fri Oct 31 21:04:37 2014 +0000 +++ b/src/cpu/x86/vm/vm_version_x86.cpp Tue Nov 04 17:16:46 2014 +0000 @@ -873,14 +873,19 @@ if (supports_bmi1()) { // tzcnt does not require VEX prefix if (FLAG_IS_DEFAULT(UseCountTrailingZerosInstruction)) { - UseCountTrailingZerosInstruction = true; + if (!UseBMI1Instructions && !FLAG_IS_DEFAULT(UseBMI1Instructions)) { + // Don't use tzcnt if BMI1 is switched off on command line. + UseCountTrailingZerosInstruction = false; + } else { + UseCountTrailingZerosInstruction = true; + } } } else if (UseCountTrailingZerosInstruction) { warning("tzcnt instruction is not available on this CPU"); FLAG_SET_DEFAULT(UseCountTrailingZerosInstruction, false); } - // BMI instructions use an encoding with VEX prefix. + // BMI instructions (except tzcnt) use an encoding with VEX prefix. // VEX prefix is generated only when AVX > 0. if (supports_bmi1() && supports_avx()) { if (FLAG_IS_DEFAULT(UseBMI1Instructions)) {
--- a/src/share/vm/c1/c1_LIRGenerator.cpp Fri Oct 31 21:04:37 2014 +0000 +++ b/src/share/vm/c1/c1_LIRGenerator.cpp Tue Nov 04 17:16:46 2014 +0000 @@ -2082,14 +2082,14 @@ LIR_Opr base_op = base.result(); LIR_Opr index_op = idx.result(); #ifndef _LP64 - if (x->base()->type()->tag() == longTag) { + if (base_op->type() == T_LONG) { base_op = new_register(T_INT); __ convert(Bytecodes::_l2i, base.result(), base_op); } if (x->has_index()) { - if (x->index()->type()->tag() == longTag) { + if (index_op->type() == T_LONG) { LIR_Opr long_index_op = index_op; - if (x->index()->type()->is_constant()) { + if (index_op->is_constant()) { long_index_op = new_register(T_LONG); __ move(index_op, long_index_op); } @@ -2104,14 +2104,14 @@ assert(!x->has_index() || index_op->type() == T_INT, "index should be an int"); #else if (x->has_index()) { - if (x->index()->type()->tag() == intTag) { - if (!x->index()->type()->is_constant()) { + if (index_op->type() == T_INT) { + if (!index_op->is_constant()) { index_op = new_register(T_LONG); __ convert(Bytecodes::_i2l, idx.result(), index_op); } } else { - assert(x->index()->type()->tag() == longTag, "must be"); - if (x->index()->type()->is_constant()) { + assert(index_op->type() == T_LONG, "must be"); + if (index_op->is_constant()) { index_op = new_register(T_LONG); __ move(idx.result(), index_op); } @@ -2192,12 +2192,12 @@ LIR_Opr index_op = idx.result(); #ifndef _LP64 - if (x->base()->type()->tag() == longTag) { + if (base_op->type() == T_LONG) { base_op = new_register(T_INT); __ convert(Bytecodes::_l2i, base.result(), base_op); } if (x->has_index()) { - if (x->index()->type()->tag() == longTag) { + if (index_op->type() == T_LONG) { index_op = new_register(T_INT); __ convert(Bytecodes::_l2i, idx.result(), index_op); } @@ -2207,7 +2207,7 @@ assert(!x->has_index() || (index_op->type() == T_INT && !index_op->is_constant()), "index should be an non-constant int"); #else if (x->has_index()) { - if (x->index()->type()->tag() == intTag) { + if (index_op->type() == T_INT) { index_op = new_register(T_LONG); __ convert(Bytecodes::_i2l, idx.result(), index_op); }
--- a/src/share/vm/classfile/classFileParser.cpp Fri Oct 31 21:04:37 2014 +0000 +++ b/src/share/vm/classfile/classFileParser.cpp Tue Nov 04 17:16:46 2014 +0000 @@ -2830,6 +2830,11 @@ "bootstrap_method_index %u has bad constant type in class file %s", bootstrap_method_index, CHECK); + + guarantee_property((operand_fill_index + 1 + argument_count) < operands->length(), + "Invalid BootstrapMethods num_bootstrap_methods or num_bootstrap_arguments value in class file %s", + CHECK); + operands->at_put(operand_fill_index++, bootstrap_method_index); operands->at_put(operand_fill_index++, argument_count); @@ -2847,7 +2852,6 @@ } assert(operand_fill_index == operands->length(), "exact fill"); - assert(ConstantPool::operand_array_length(operands) == attribute_array_length, "correct decode"); u1* current_end = cfs->current(); guarantee_property(current_end == current_start + attribute_byte_length, @@ -4161,8 +4165,12 @@ tty->print("[Loaded %s from %s]\n", this_klass->external_name(), cfs->source()); } else if (class_loader.is_null()) { - if (THREAD->is_Java_thread()) { - Klass* caller = ((JavaThread*)THREAD)->security_get_caller_class(1); + Klass* caller = + THREAD->is_Java_thread() + ? ((JavaThread*)THREAD)->security_get_caller_class(1) + : NULL; + // caller can be NULL, for example, during a JVMTI VM_Init hook + if (caller != NULL) { tty->print("[Loaded %s by instance of %s]\n", this_klass->external_name(), InstanceKlass::cast(caller)->external_name());
--- a/src/share/vm/classfile/classLoader.cpp Fri Oct 31 21:04:37 2014 +0000 +++ b/src/share/vm/classfile/classLoader.cpp Tue Nov 04 17:16:46 2014 +0000 @@ -90,6 +90,7 @@ typedef jboolean (JNICALL *ReadEntry_t)(jzfile *zip, jzentry *entry, unsigned char *buf, char *namebuf); typedef jboolean (JNICALL *ReadMappedEntry_t)(jzfile *zip, jzentry *entry, unsigned char **buf, char *namebuf); typedef jzentry* (JNICALL *GetNextEntry_t)(jzfile *zip, jint n); +typedef jint (JNICALL *Crc32_t)(jint crc, const jbyte *buf, jint len); static ZipOpen_t ZipOpen = NULL; static ZipClose_t ZipClose = NULL; @@ -98,6 +99,7 @@ static ReadMappedEntry_t ReadMappedEntry = NULL; static GetNextEntry_t GetNextEntry = NULL; static canonicalize_fn_t CanonicalizeEntry = NULL; +static Crc32_t Crc32 = NULL; // Globals @@ -810,9 +812,11 @@ ReadEntry = CAST_TO_FN_PTR(ReadEntry_t, os::dll_lookup(handle, "ZIP_ReadEntry")); ReadMappedEntry = CAST_TO_FN_PTR(ReadMappedEntry_t, os::dll_lookup(handle, "ZIP_ReadMappedEntry")); GetNextEntry = CAST_TO_FN_PTR(GetNextEntry_t, os::dll_lookup(handle, "ZIP_GetNextEntry")); + Crc32 = CAST_TO_FN_PTR(Crc32_t, os::dll_lookup(handle, "ZIP_CRC32")); // ZIP_Close is not exported on Windows in JDK5.0 so don't abort if ZIP_Close is NULL - if (ZipOpen == NULL || FindEntry == NULL || ReadEntry == NULL || GetNextEntry == NULL) { + if (ZipOpen == NULL || FindEntry == NULL || ReadEntry == NULL || + GetNextEntry == NULL || Crc32 == NULL) { vm_exit_during_initialization("Corrupted ZIP library", path); } @@ -822,6 +826,11 @@ // This lookup only works on 1.3. Do not check for non-null here } +int ClassLoader::crc32(int crc, const char* buf, int len) { + assert(Crc32 != NULL, "ZIP_CRC32 is not found"); + return (*Crc32)(crc, (const jbyte*)buf, len); +} + // PackageInfo data exists in order to support the java.lang.Package // class. A Package object provides information about a java package // (version, vendor, etc.) which originates in the manifest of the jar
--- a/src/share/vm/classfile/classLoader.hpp Fri Oct 31 21:04:37 2014 +0000 +++ b/src/share/vm/classfile/classLoader.hpp Tue Nov 04 17:16:46 2014 +0000 @@ -228,6 +228,7 @@ // to avoid confusing the zip library static bool get_canonical_path(const char* orig, char* out, int len); public: + static int crc32(int crc, const char* buf, int len); static bool update_class_path_entry_list(const char *path, bool check_for_duplicates, bool throw_exception=true);
--- a/src/share/vm/classfile/stackMapFrame.cpp Fri Oct 31 21:04:37 2014 +0000 +++ b/src/share/vm/classfile/stackMapFrame.cpp Tue Nov 04 17:16:46 2014 +0000 @@ -148,7 +148,7 @@ VerificationType* from, VerificationType* to, int32_t len, TRAPS) const { int32_t i = 0; for (i = 0; i < len; i++) { - if (!to[i].is_assignable_from(from[i], verifier(), THREAD)) { + if (!to[i].is_assignable_from(from[i], verifier(), false, THREAD)) { break; } } @@ -245,7 +245,7 @@ } VerificationType top = _stack[--_stack_size]; bool subtype = type.is_assignable_from( - top, verifier(), CHECK_(VerificationType::bogus_type())); + top, verifier(), false, CHECK_(VerificationType::bogus_type())); if (!subtype) { verifier()->verify_error( ErrorContext::bad_type(_offset, stack_top_ctx(), @@ -265,7 +265,7 @@ return VerificationType::bogus_type(); } bool subtype = type.is_assignable_from(_locals[index], - verifier(), CHECK_(VerificationType::bogus_type())); + verifier(), false, CHECK_(VerificationType::bogus_type())); if (!subtype) { verifier()->verify_error( ErrorContext::bad_type(_offset, @@ -288,14 +288,14 @@ "get long/double overflows locals"); return; } - bool subtype = type1.is_assignable_from(_locals[index], verifier(), CHECK); + bool subtype = type1.is_assignable_from(_locals[index], verifier(), false, CHECK); if (!subtype) { verifier()->verify_error( ErrorContext::bad_type(_offset, TypeOrigin::local(index, this), TypeOrigin::implicit(type1)), "Bad local variable type"); } else { - subtype = type2.is_assignable_from(_locals[index + 1], verifier(), CHECK); + subtype = type2.is_assignable_from(_locals[index + 1], verifier(), false, CHECK); if (!subtype) { /* Unreachable? All local store routines convert a split long or double * into a TOP during the store. So we should never end up seeing an
--- a/src/share/vm/classfile/stackMapFrame.hpp Fri Oct 31 21:04:37 2014 +0000 +++ b/src/share/vm/classfile/stackMapFrame.hpp Tue Nov 04 17:16:46 2014 +0000 @@ -234,7 +234,7 @@ if (_stack_size != 0) { VerificationType top = _stack[_stack_size - 1]; bool subtype = type.is_assignable_from( - top, verifier(), CHECK_(VerificationType::bogus_type())); + top, verifier(), false, CHECK_(VerificationType::bogus_type())); if (subtype) { --_stack_size; return top; @@ -249,9 +249,9 @@ assert(type2.is_long() || type2.is_double(), "must be long/double_2"); if (_stack_size >= 2) { VerificationType top1 = _stack[_stack_size - 1]; - bool subtype1 = type1.is_assignable_from(top1, verifier(), CHECK); + bool subtype1 = type1.is_assignable_from(top1, verifier(), false, CHECK); VerificationType top2 = _stack[_stack_size - 2]; - bool subtype2 = type2.is_assignable_from(top2, verifier(), CHECK); + bool subtype2 = type2.is_assignable_from(top2, verifier(), false, CHECK); if (subtype1 && subtype2) { _stack_size -= 2; return;
--- a/src/share/vm/classfile/verificationType.cpp Fri Oct 31 21:04:37 2014 +0000 +++ b/src/share/vm/classfile/verificationType.cpp Tue Nov 04 17:16:46 2014 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2014, 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 @@ -42,7 +42,8 @@ } bool VerificationType::is_reference_assignable_from( - const VerificationType& from, ClassVerifier* context, TRAPS) const { + const VerificationType& from, ClassVerifier* context, + bool from_field_is_protected, TRAPS) const { instanceKlassHandle klass = context->current_class(); if (from.is_null()) { // null is assignable to any reference @@ -62,9 +63,11 @@ Handle(THREAD, klass->protection_domain()), true, CHECK_false); KlassHandle this_class(THREAD, obj); - if (this_class->is_interface()) { - // We treat interfaces as java.lang.Object, including - // java.lang.Cloneable and java.io.Serializable + if (this_class->is_interface() && (!from_field_is_protected || + from.name() != vmSymbols::java_lang_Object())) { + // If we are not trying to access a protected field or method in + // java.lang.Object then we treat interfaces as java.lang.Object, + // including java.lang.Cloneable and java.io.Serializable. return true; } else if (from.is_object()) { Klass* from_class = SystemDictionary::resolve_or_fail( @@ -76,7 +79,8 @@ VerificationType comp_this = get_component(context, CHECK_false); VerificationType comp_from = from.get_component(context, CHECK_false); if (!comp_this.is_bogus() && !comp_from.is_bogus()) { - return comp_this.is_assignable_from(comp_from, context, CHECK_false); + return comp_this.is_assignable_from(comp_from, context, + from_field_is_protected, CHECK_false); } } return false;
--- a/src/share/vm/classfile/verificationType.hpp Fri Oct 31 21:04:37 2014 +0000 +++ b/src/share/vm/classfile/verificationType.hpp Tue Nov 04 17:16:46 2014 +0000 @@ -265,7 +265,8 @@ // is assignable to another. Returns true if one can assign 'from' to // this. bool is_assignable_from( - const VerificationType& from, ClassVerifier* context, TRAPS) const { + const VerificationType& from, ClassVerifier* context, + bool from_field_is_protected, TRAPS) const { if (equals(from) || is_bogus()) { return true; } else { @@ -286,7 +287,9 @@ return from.is_integer(); default: if (is_reference() && from.is_reference()) { - return is_reference_assignable_from(from, context, CHECK_false); + return is_reference_assignable_from(from, context, + from_field_is_protected, + CHECK_false); } else { return false; } @@ -308,7 +311,8 @@ private: bool is_reference_assignable_from( - const VerificationType&, ClassVerifier*, TRAPS) const; + const VerificationType&, ClassVerifier*, bool from_field_is_protected, + TRAPS) const; }; #endif // SHARE_VM_CLASSFILE_VERIFICATIONTYPE_HPP
--- a/src/share/vm/classfile/verifier.cpp Fri Oct 31 21:04:37 2014 +0000 +++ b/src/share/vm/classfile/verifier.cpp Tue Nov 04 17:16:46 2014 +0000 @@ -1737,7 +1737,7 @@ VerificationType throwable = VerificationType::reference_type(vmSymbols::java_lang_Throwable()); bool is_subclass = throwable.is_assignable_from( - catch_type, this, CHECK_VERIFY(this)); + catch_type, this, false, CHECK_VERIFY(this)); if (!is_subclass) { // 4286534: should throw VerifyError according to recent spec change verify_error(ErrorContext::bad_type(handler_pc, @@ -2192,7 +2192,7 @@ stack_object_type = current_type(); } is_assignable = target_class_type.is_assignable_from( - stack_object_type, this, CHECK_VERIFY(this)); + stack_object_type, this, false, CHECK_VERIFY(this)); if (!is_assignable) { verify_error(ErrorContext::bad_type(bci, current_frame->stack_top_ctx(), @@ -2219,7 +2219,7 @@ // It's protected access, check if stack object is assignable to // current class. is_assignable = current_type().is_assignable_from( - stack_object_type, this, CHECK_VERIFY(this)); + stack_object_type, this, true, CHECK_VERIFY(this)); if (!is_assignable) { verify_error(ErrorContext::bad_type(bci, current_frame->stack_top_ctx(), @@ -2492,7 +2492,7 @@ instanceKlassHandle mh(THREAD, m->method_holder()); if (m->is_protected() && !mh->is_same_class_package(_klass())) { bool assignable = current_type().is_assignable_from( - objectref_type, this, CHECK_VERIFY(this)); + objectref_type, this, true, CHECK_VERIFY(this)); if (!assignable) { verify_error(ErrorContext::bad_type(bci, TypeOrigin::cp(new_class_index, objectref_type), @@ -2667,11 +2667,11 @@ bool have_imr_indirect = cp->tag_at(index).value() == JVM_CONSTANT_InterfaceMethodref; if (!current_class()->is_anonymous()) { subtype = ref_class_type.is_assignable_from( - current_type(), this, CHECK_VERIFY(this)); + current_type(), this, false, CHECK_VERIFY(this)); } else { VerificationType host_klass_type = VerificationType::reference_type(current_class()->host_klass()->name()); - subtype = ref_class_type.is_assignable_from(host_klass_type, this, CHECK_VERIFY(this)); + subtype = ref_class_type.is_assignable_from(host_klass_type, this, false, CHECK_VERIFY(this)); // If invokespecial of IMR, need to recheck for same or // direct interface relative to the host class @@ -2715,7 +2715,7 @@ VerificationType top = current_frame->pop_stack(CHECK_VERIFY(this)); VerificationType hosttype = VerificationType::reference_type(current_class()->host_klass()->name()); - bool subtype = hosttype.is_assignable_from(top, this, CHECK_VERIFY(this)); + bool subtype = hosttype.is_assignable_from(top, this, false, CHECK_VERIFY(this)); if (!subtype) { verify_error( ErrorContext::bad_type(current_frame->offset(), current_frame->stack_top_ctx(), @@ -2740,7 +2740,7 @@ // It's protected access, check if stack object is // assignable to current class. bool is_assignable = current_type().is_assignable_from( - stack_object_type, this, CHECK_VERIFY(this)); + stack_object_type, this, true, CHECK_VERIFY(this)); if (!is_assignable) { if (ref_class_type.name() == vmSymbols::java_lang_Object() && stack_object_type.is_array() @@ -2923,7 +2923,7 @@ "Method expects a return value"); return; } - bool match = return_type.is_assignable_from(type, this, CHECK_VERIFY(this)); + bool match = return_type.is_assignable_from(type, this, false, CHECK_VERIFY(this)); if (!match) { verify_error(ErrorContext::bad_type(bci, current_frame->stack_top_ctx(), TypeOrigin::signature(return_type)),
--- a/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp Fri Oct 31 21:04:37 2014 +0000 +++ b/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp Tue Nov 04 17:16:46 2014 +0000 @@ -2733,10 +2733,12 @@ } } -void CompactibleFreeListSpace:: par_get_chunk_of_blocks(size_t word_sz, size_t n, AdaptiveFreeList<FreeChunk>* fl) { - assert(fl->count() == 0, "Precondition."); - assert(word_sz < CompactibleFreeListSpace::IndexSetSize, - "Precondition"); +// Used by par_get_chunk_of_blocks() for the chunks from the +// indexed_free_lists. Looks for a chunk with size that is a multiple +// of "word_sz" and if found, splits it into "word_sz" chunks and add +// to the free list "fl". "n" is the maximum number of chunks to +// be added to "fl". +bool CompactibleFreeListSpace:: par_get_chunk_of_blocks_IFL(size_t word_sz, size_t n, AdaptiveFreeList<FreeChunk>* fl) { // We'll try all multiples of word_sz in the indexed set, starting with // word_sz itself and, if CMSSplitIndexedFreeListBlocks, try larger multiples, @@ -2817,11 +2819,15 @@ Mutex::_no_safepoint_check_flag); ssize_t births = _indexedFreeList[word_sz].split_births() + num; _indexedFreeList[word_sz].set_split_births(births); - return; + return true; } } + return found; } - // Otherwise, we'll split a block from the dictionary. +} + +FreeChunk* CompactibleFreeListSpace::get_n_way_chunk_to_split(size_t word_sz, size_t n) { + FreeChunk* fc = NULL; FreeChunk* rem_fc = NULL; size_t rem; @@ -2832,16 +2838,12 @@ fc = dictionary()->get_chunk(MAX2(n * word_sz, _dictionary->min_size()), FreeBlockDictionary<FreeChunk>::atLeast); if (fc != NULL) { - _bt.allocated((HeapWord*)fc, fc->size(), true /* reducing */); // update _unallocated_blk - dictionary()->dict_census_update(fc->size(), - true /*split*/, - false /*birth*/); break; } else { n--; } } - if (fc == NULL) return; + if (fc == NULL) return NULL; // Otherwise, split up that block. assert((ssize_t)n >= 1, "Control point invariant"); assert(fc->is_free(), "Error: should be a free block"); @@ -2863,10 +2865,14 @@ // dictionary and return, leaving "fl" empty. if (n == 0) { returnChunkToDictionary(fc); - assert(fl->count() == 0, "We never allocated any blocks"); - return; + return NULL; } + _bt.allocated((HeapWord*)fc, fc->size(), true /* reducing */); // update _unallocated_blk + dictionary()->dict_census_update(fc->size(), + true /*split*/, + false /*birth*/); + // First return the remainder, if any. // Note that we hold the lock until we decide if we're going to give // back the remainder to the dictionary, since a concurrent allocation @@ -2899,7 +2905,24 @@ _indexedFreeList[rem].return_chunk_at_head(rem_fc); smallSplitBirth(rem); } - assert((ssize_t)n > 0 && fc != NULL, "Consistency"); + assert(n * word_sz == fc->size(), + err_msg("Chunk size " SIZE_FORMAT " is not exactly splittable by " + SIZE_FORMAT " sized chunks of size " SIZE_FORMAT, + fc->size(), n, word_sz)); + return fc; +} + +void CompactibleFreeListSpace:: par_get_chunk_of_blocks_dictionary(size_t word_sz, size_t targetted_number_of_chunks, AdaptiveFreeList<FreeChunk>* fl) { + + FreeChunk* fc = get_n_way_chunk_to_split(word_sz, targetted_number_of_chunks); + + if (fc == NULL) { + return; + } + + size_t n = fc->size() / word_sz; + + assert((ssize_t)n > 0, "Consistency"); // Now do the splitting up. // Must do this in reverse order, so that anybody attempting to // access the main chunk sees it as a single free block until we @@ -2947,6 +2970,20 @@ assert(fl->tail()->next() == NULL, "List invariant."); } +void CompactibleFreeListSpace:: par_get_chunk_of_blocks(size_t word_sz, size_t n, AdaptiveFreeList<FreeChunk>* fl) { + assert(fl->count() == 0, "Precondition."); + assert(word_sz < CompactibleFreeListSpace::IndexSetSize, + "Precondition"); + + if (par_get_chunk_of_blocks_IFL(word_sz, n, fl)) { + // Got it + return; + } + + // Otherwise, we'll split a block from the dictionary. + par_get_chunk_of_blocks_dictionary(word_sz, n, fl); +} + // Set up the space's par_seq_tasks structure for work claiming // for parallel rescan. See CMSParRemarkTask where this is currently used. // XXX Need to suitably abstract and generalize this and the next
--- a/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp Fri Oct 31 21:04:37 2014 +0000 +++ b/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp Tue Nov 04 17:16:46 2014 +0000 @@ -172,6 +172,20 @@ // list of size "word_sz", and must now be decremented. void par_get_chunk_of_blocks(size_t word_sz, size_t n, AdaptiveFreeList<FreeChunk>* fl); + // Used by par_get_chunk_of_blocks() for the chunks from the + // indexed_free_lists. + bool par_get_chunk_of_blocks_IFL(size_t word_sz, size_t n, AdaptiveFreeList<FreeChunk>* fl); + + // Used by par_get_chunk_of_blocks_dictionary() to get a chunk + // evenly splittable into "n" "word_sz" chunks. Returns that + // evenly splittable chunk. May split a larger chunk to get the + // evenly splittable chunk. + FreeChunk* get_n_way_chunk_to_split(size_t word_sz, size_t n); + + // Used by par_get_chunk_of_blocks() for the chunks from the + // dictionary. + void par_get_chunk_of_blocks_dictionary(size_t word_sz, size_t n, AdaptiveFreeList<FreeChunk>* fl); + // Allocation helper functions // Allocate using a strategy that takes from the indexed free lists // first. This allocation strategy assumes a companion sweeping
--- a/src/share/vm/gc_implementation/g1/concurrentMark.cpp Fri Oct 31 21:04:37 2014 +0000 +++ b/src/share/vm/gc_implementation/g1/concurrentMark.cpp Tue Nov 04 17:16:46 2014 +0000 @@ -130,7 +130,10 @@ storage->set_mapping_changed_listener(&_listener); } -void CMBitMapMappingChangedListener::on_commit(uint start_region, size_t num_regions) { +void CMBitMapMappingChangedListener::on_commit(uint start_region, size_t num_regions, bool zero_filled) { + if (zero_filled) { + return; + } // We need to clear the bitmap on commit, removing any existing information. MemRegion mr(G1CollectedHeap::heap()->bottom_addr_for_region(start_region), num_regions * HeapRegion::GrainWords); _bm->clearRange(mr);
--- a/src/share/vm/gc_implementation/g1/concurrentMark.hpp Fri Oct 31 21:04:37 2014 +0000 +++ b/src/share/vm/gc_implementation/g1/concurrentMark.hpp Tue Nov 04 17:16:46 2014 +0000 @@ -127,7 +127,7 @@ void set_bitmap(CMBitMap* bm) { _bm = bm; } - virtual void on_commit(uint start_idx, size_t num_regions); + virtual void on_commit(uint start_idx, size_t num_regions, bool zero_filled); }; class CMBitMap : public CMBitMapRO {
--- a/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.cpp Fri Oct 31 21:04:37 2014 +0000 +++ b/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.cpp Tue Nov 04 17:16:46 2014 +0000 @@ -32,13 +32,6 @@ PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC -void G1BlockOffsetSharedArrayMappingChangedListener::on_commit(uint start_idx, size_t num_regions) { - // Nothing to do. The BOT is hard-wired to be part of the HeapRegion, and we cannot - // retrieve it here since this would cause firing of several asserts. The code - // executed after commit of a region already needs to do some re-initialization of - // the HeapRegion, so we combine that. -} - ////////////////////////////////////////////////////////////////////// // G1BlockOffsetSharedArray ////////////////////////////////////////////////////////////////////// @@ -72,26 +65,16 @@ return (delta & right_n_bits(LogN_words)) == (size_t)NoBits; } -void G1BlockOffsetSharedArray::set_offset_array(HeapWord* left, HeapWord* right, u_char offset) { - set_offset_array(index_for(left), index_for(right -1), offset); -} - ////////////////////////////////////////////////////////////////////// // G1BlockOffsetArray ////////////////////////////////////////////////////////////////////// G1BlockOffsetArray::G1BlockOffsetArray(G1BlockOffsetSharedArray* array, - MemRegion mr, bool init_to_zero) : + MemRegion mr) : G1BlockOffsetTable(mr.start(), mr.end()), _unallocated_block(_bottom), - _array(array), _gsp(NULL), - _init_to_zero(init_to_zero) { + _array(array), _gsp(NULL) { assert(_bottom <= _end, "arguments out of order"); - if (!_init_to_zero) { - // initialize cards to point back to mr.start() - set_remainder_to_point_to_start(mr.start() + N_words, mr.end()); - _array->set_offset_array(0, 0); // set first card to 0 - } } void G1BlockOffsetArray::set_space(G1OffsetTableContigSpace* sp) { @@ -181,93 +164,6 @@ DEBUG_ONLY(check_all_cards(start_card, end_card);) } -// The block [blk_start, blk_end) has been allocated; -// adjust the block offset table to represent this information; -// right-open interval: [blk_start, blk_end) -void -G1BlockOffsetArray::alloc_block(HeapWord* blk_start, HeapWord* blk_end) { - mark_block(blk_start, blk_end); - allocated(blk_start, blk_end); -} - -// Adjust BOT to show that a previously whole block has been split -// into two. -void G1BlockOffsetArray::split_block(HeapWord* blk, size_t blk_size, - size_t left_blk_size) { - // Verify that the BOT shows [blk, blk + blk_size) to be one block. - verify_single_block(blk, blk_size); - // Update the BOT to indicate that [blk + left_blk_size, blk + blk_size) - // is one single block. - mark_block(blk + left_blk_size, blk + blk_size); -} - - -// Action_mark - update the BOT for the block [blk_start, blk_end). -// Current typical use is for splitting a block. -// Action_single - update the BOT for an allocation. -// Action_verify - BOT verification. -void G1BlockOffsetArray::do_block_internal(HeapWord* blk_start, - HeapWord* blk_end, - Action action) { - assert(Universe::heap()->is_in_reserved(blk_start), - "reference must be into the heap"); - assert(Universe::heap()->is_in_reserved(blk_end-1), - "limit must be within the heap"); - // This is optimized to make the test fast, assuming we only rarely - // cross boundaries. - uintptr_t end_ui = (uintptr_t)(blk_end - 1); - uintptr_t start_ui = (uintptr_t)blk_start; - // Calculate the last card boundary preceding end of blk - intptr_t boundary_before_end = (intptr_t)end_ui; - clear_bits(boundary_before_end, right_n_bits(LogN)); - if (start_ui <= (uintptr_t)boundary_before_end) { - // blk starts at or crosses a boundary - // Calculate index of card on which blk begins - size_t start_index = _array->index_for(blk_start); - // Index of card on which blk ends - size_t end_index = _array->index_for(blk_end - 1); - // Start address of card on which blk begins - HeapWord* boundary = _array->address_for_index(start_index); - assert(boundary <= blk_start, "blk should start at or after boundary"); - if (blk_start != boundary) { - // blk starts strictly after boundary - // adjust card boundary and start_index forward to next card - boundary += N_words; - start_index++; - } - assert(start_index <= end_index, "monotonicity of index_for()"); - assert(boundary <= (HeapWord*)boundary_before_end, "tautology"); - switch (action) { - case Action_mark: { - if (init_to_zero()) { - _array->set_offset_array(start_index, boundary, blk_start); - break; - } // Else fall through to the next case - } - case Action_single: { - _array->set_offset_array(start_index, boundary, blk_start); - // We have finished marking the "offset card". We need to now - // mark the subsequent cards that this blk spans. - if (start_index < end_index) { - HeapWord* rem_st = _array->address_for_index(start_index) + N_words; - HeapWord* rem_end = _array->address_for_index(end_index) + N_words; - set_remainder_to_point_to_start(rem_st, rem_end); - } - break; - } - case Action_check: { - _array->check_offset_array(start_index, boundary, blk_start); - // We have finished checking the "offset card". We need to now - // check the subsequent cards that this blk spans. - check_all_cards(start_index + 1, end_index); - break; - } - default: - ShouldNotReachHere(); - } - } -} - // The card-interval [start_card, end_card] is a closed interval; this // is an expensive check -- use with care and only under protection of // suitable flag. @@ -306,25 +202,6 @@ } } -// The range [blk_start, blk_end) represents a single contiguous block -// of storage; modify the block offset table to represent this -// information; Right-open interval: [blk_start, blk_end) -// NOTE: this method does _not_ adjust _unallocated_block. -void -G1BlockOffsetArray::single_block(HeapWord* blk_start, HeapWord* blk_end) { - do_block_internal(blk_start, blk_end, Action_single); -} - -// Mark the BOT such that if [blk_start, blk_end) straddles a card -// boundary, the card following the first such boundary is marked -// with the appropriate offset. -// NOTE: this method does _not_ adjust _unallocated_block or -// any cards subsequent to the first one. -void -G1BlockOffsetArray::mark_block(HeapWord* blk_start, HeapWord* blk_end) { - do_block_internal(blk_start, blk_end, Action_mark); -} - HeapWord* G1BlockOffsetArray::block_start_unsafe(const void* addr) { assert(_bottom <= addr && addr < _end, "addr must be covered by this Array"); @@ -397,57 +274,13 @@ return forward_to_block_containing_addr_const(q, n, addr); } -HeapWord* G1BlockOffsetArray::block_start_careful(const void* addr) const { - assert(_array->offset_array(0) == 0, "objects can't cross covered areas"); - - assert(_bottom <= addr && addr < _end, - "addr must be covered by this Array"); - // Must read this exactly once because it can be modified by parallel - // allocation. - HeapWord* ub = _unallocated_block; - if (BlockOffsetArrayUseUnallocatedBlock && addr >= ub) { - assert(ub < _end, "tautology (see above)"); - return ub; - } - - // Otherwise, find the block start using the table, but taking - // care (cf block_start_unsafe() above) not to parse any objects/blocks - // on the cards themsleves. - size_t index = _array->index_for(addr); - assert(_array->address_for_index(index) == addr, - "arg should be start of card"); - - HeapWord* q = (HeapWord*)addr; - uint offset; - do { - offset = _array->offset_array(index--); - q -= offset; - } while (offset == N_words); - assert(q <= addr, "block start should be to left of arg"); - return q; -} - // Note that the committed size of the covered space may have changed, // so the table size might also wish to change. void G1BlockOffsetArray::resize(size_t new_word_size) { HeapWord* new_end = _bottom + new_word_size; - if (_end < new_end && !init_to_zero()) { - // verify that the old and new boundaries are also card boundaries - assert(_array->is_card_boundary(_end), - "_end not a card boundary"); - assert(_array->is_card_boundary(new_end), - "new _end would not be a card boundary"); - // set all the newly added cards - _array->set_offset_array(_end, new_end, N_words); - } _end = new_end; // update _end } -void G1BlockOffsetArray::set_region(MemRegion mr) { - _bottom = mr.start(); - _end = mr.end(); -} - // // threshold_ // | _index_ @@ -607,7 +440,7 @@ G1BlockOffsetArrayContigSpace:: G1BlockOffsetArrayContigSpace(G1BlockOffsetSharedArray* array, MemRegion mr) : - G1BlockOffsetArray(array, mr, true) + G1BlockOffsetArray(array, mr) { _next_offset_threshold = NULL; _next_offset_index = 0; @@ -642,15 +475,6 @@ return _next_offset_threshold; } -void G1BlockOffsetArrayContigSpace::zero_bottom_entry() { - assert(!Universe::heap()->is_in_reserved(_array->_offset_array), - "just checking"); - size_t bottom_index = _array->index_for(_bottom); - assert(_array->address_for_index(bottom_index) == _bottom, - "Precondition of call"); - _array->set_offset_array(bottom_index, 0); -} - void G1BlockOffsetArrayContigSpace::set_for_starts_humongous(HeapWord* new_top) { assert(new_top <= _end, "_end should have already been updated");
--- a/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.hpp Fri Oct 31 21:04:37 2014 +0000 +++ b/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.hpp Tue Nov 04 17:16:46 2014 +0000 @@ -109,7 +109,12 @@ class G1BlockOffsetSharedArrayMappingChangedListener : public G1MappingChangedListener { public: - virtual void on_commit(uint start_idx, size_t num_regions); + virtual void on_commit(uint start_idx, size_t num_regions, bool zero_filled) { + // Nothing to do. The BOT is hard-wired to be part of the HeapRegion, and we cannot + // retrieve it here since this would cause firing of several asserts. The code + // executed after commit of a region already needs to do some re-initialization of + // the HeapRegion, so we combine that. + } }; // This implementation of "G1BlockOffsetTable" divides the covered region @@ -153,8 +158,6 @@ // For performance these have to devolve to array accesses in product builds. inline u_char offset_array(size_t index) const; - void set_offset_array(HeapWord* left, HeapWord* right, u_char offset); - void set_offset_array_raw(size_t index, u_char offset) { _offset_array[index] = offset; } @@ -165,8 +168,6 @@ inline void set_offset_array(size_t left, size_t right, u_char offset); - inline void check_offset_array(size_t index, HeapWord* high, HeapWord* low) const; - bool is_card_boundary(HeapWord* p) const; public: @@ -193,8 +194,6 @@ // G1BlockOffsetTable(s) to initialize cards. G1BlockOffsetSharedArray(MemRegion heap, G1RegionToSpaceMapper* storage); - void set_bottom(HeapWord* new_bottom); - // Return the appropriate index into "_offset_array" for "p". inline size_t index_for(const void* p) const; inline size_t index_for_raw(const void* p) const; @@ -220,14 +219,6 @@ LogN = G1BlockOffsetSharedArray::LogN }; - // The following enums are used by do_block_helper - enum Action { - Action_single, // BOT records a single block (see single_block()) - Action_mark, // BOT marks the start of a block (see mark_block()) - Action_check // Check that BOT records block correctly - // (see verify_single_block()). - }; - // This is the array, which can be shared by several BlockOffsetArray's // servicing different G1BlockOffsetSharedArray* _array; @@ -235,10 +226,6 @@ // The space that owns this subregion. G1OffsetTableContigSpace* _gsp; - // If true, array entries are initialized to 0; otherwise, they are - // initialized to point backwards to the beginning of the covered region. - bool _init_to_zero; - // The portion [_unallocated_block, _sp.end()) of the space that // is a single block known not to contain any objects. // NOTE: See BlockOffsetArrayUseUnallocatedBlock flag. @@ -253,9 +240,6 @@ // that is closed: [start_index, end_index] void set_remainder_to_point_to_start_incl(size_t start, size_t end); - // A helper function for BOT adjustment/verification work - void do_block_internal(HeapWord* blk_start, HeapWord* blk_end, Action action); - protected: G1OffsetTableContigSpace* gsp() const { return _gsp; } @@ -303,11 +287,9 @@ public: // The space may not have it's bottom and top set yet, which is why the - // region is passed as a parameter. If "init_to_zero" is true, the - // elements of the array are initialized to zero. Otherwise, they are - // initialized to point backwards to the beginning. - G1BlockOffsetArray(G1BlockOffsetSharedArray* array, MemRegion mr, - bool init_to_zero); + // region is passed as a parameter. The elements of the array are + // initialized to zero. + G1BlockOffsetArray(G1BlockOffsetSharedArray* array, MemRegion mr); // Note: this ought to be part of the constructor, but that would require // "this" to be passed as a parameter to a member constructor for @@ -315,114 +297,19 @@ // This would be legal C++, but MS VC++ doesn't allow it. void set_space(G1OffsetTableContigSpace* sp); - // Resets the covered region to the given "mr". - void set_region(MemRegion mr); - // Resets the covered region to one with the same _bottom as before but // the "new_word_size". void resize(size_t new_word_size); - // These must be guaranteed to work properly (i.e., do nothing) - // when "blk_start" ("blk" for second version) is "NULL". - virtual void alloc_block(HeapWord* blk_start, HeapWord* blk_end); - virtual void alloc_block(HeapWord* blk, size_t size) { - alloc_block(blk, blk + size); - } - - // The following methods are useful and optimized for a - // general, non-contiguous space. - - // Given a block [blk_start, blk_start + full_blk_size), and - // a left_blk_size < full_blk_size, adjust the BOT to show two - // blocks [blk_start, blk_start + left_blk_size) and - // [blk_start + left_blk_size, blk_start + full_blk_size). - // It is assumed (and verified in the non-product VM) that the - // BOT was correct for the original block. - void split_block(HeapWord* blk_start, size_t full_blk_size, - size_t left_blk_size); - - // Adjust the BOT to show that it has a single block in the - // range [blk_start, blk_start + size). All necessary BOT - // cards are adjusted, but _unallocated_block isn't. - void single_block(HeapWord* blk_start, HeapWord* blk_end); - void single_block(HeapWord* blk, size_t size) { - single_block(blk, blk + size); - } - - // Adjust BOT to show that it has a block in the range - // [blk_start, blk_start + size). Only the first card - // of BOT is touched. It is assumed (and verified in the - // non-product VM) that the remaining cards of the block - // are correct. - void mark_block(HeapWord* blk_start, HeapWord* blk_end); - void mark_block(HeapWord* blk, size_t size) { - mark_block(blk, blk + size); - } - - // Adjust _unallocated_block to indicate that a particular - // block has been newly allocated or freed. It is assumed (and - // verified in the non-product VM) that the BOT is correct for - // the given block. - inline void allocated(HeapWord* blk_start, HeapWord* blk_end) { - // Verify that the BOT shows [blk, blk + blk_size) to be one block. - verify_single_block(blk_start, blk_end); - if (BlockOffsetArrayUseUnallocatedBlock) { - _unallocated_block = MAX2(_unallocated_block, blk_end); - } - } - - inline void allocated(HeapWord* blk, size_t size) { - allocated(blk, blk + size); - } - - inline void freed(HeapWord* blk_start, HeapWord* blk_end); - - inline void freed(HeapWord* blk, size_t size); - virtual HeapWord* block_start_unsafe(const void* addr); virtual HeapWord* block_start_unsafe_const(const void* addr) const; - // Requires "addr" to be the start of a card and returns the - // start of the block that contains the given address. - HeapWord* block_start_careful(const void* addr) const; - - // If true, initialize array slots with no allocated blocks to zero. - // Otherwise, make them point back to the front. - bool init_to_zero() { return _init_to_zero; } - - // Verification & debugging - ensure that the offset table reflects the fact - // that the block [blk_start, blk_end) or [blk, blk + size) is a - // single block of storage. NOTE: can;t const this because of - // call to non-const do_block_internal() below. - inline void verify_single_block(HeapWord* blk_start, HeapWord* blk_end) { - if (VerifyBlockOffsetArray) { - do_block_internal(blk_start, blk_end, Action_check); - } - } - - inline void verify_single_block(HeapWord* blk, size_t size) { - verify_single_block(blk, blk + size); - } - // Used by region verification. Checks that the contents of the // BOT reflect that there's a single object that spans the address // range [obj_start, obj_start + word_size); returns true if this is // the case, returns false if it's not. bool verify_for_object(HeapWord* obj_start, size_t word_size) const; - // Verify that the given block is before _unallocated_block - inline void verify_not_unallocated(HeapWord* blk_start, - HeapWord* blk_end) const { - if (BlockOffsetArrayUseUnallocatedBlock) { - assert(blk_start < blk_end, "Block inconsistency?"); - assert(blk_end <= _unallocated_block, "_unallocated_block problem"); - } - } - - inline void verify_not_unallocated(HeapWord* blk, size_t size) const { - verify_not_unallocated(blk, blk + size); - } - void check_all_cards(size_t left_card, size_t right_card) const; virtual void print_on(outputStream* out) PRODUCT_RETURN; @@ -445,14 +332,12 @@ blk_start, blk_end); } - // Variant of zero_bottom_entry that does not check for availability of the + // Zero out the entry for _bottom (offset will be zero). Does not check for availability of the // memory first. void zero_bottom_entry_raw(); // Variant of initialize_threshold that does not check for availability of the // memory first. HeapWord* initialize_threshold_raw(); - // Zero out the entry for _bottom (offset will be zero). - void zero_bottom_entry(); public: G1BlockOffsetArrayContigSpace(G1BlockOffsetSharedArray* array, MemRegion mr);
--- a/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.inline.hpp Fri Oct 31 21:04:37 2014 +0000 +++ b/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.inline.hpp Tue Nov 04 17:16:46 2014 +0000 @@ -91,13 +91,6 @@ } } -void G1BlockOffsetSharedArray::check_offset_array(size_t index, HeapWord* high, HeapWord* low) const { - check_index(index, "index out of range"); - assert(high >= low, "addresses out of order"); - check_offset(pointer_delta(high, low), "offset too large"); - assert(_offset_array[index] == pointer_delta(high, low), "Wrong offset"); -} - // Variant of index_for that does not check the index for validity. inline size_t G1BlockOffsetSharedArray::index_for_raw(const void* p) const { return pointer_delta((char*)p, _reserved.start(), sizeof(char)) >> LogN; @@ -193,28 +186,4 @@ return q; } -////////////////////////////////////////////////////////////////////////// -// BlockOffsetArrayNonContigSpace inlines -////////////////////////////////////////////////////////////////////////// -inline void G1BlockOffsetArray::freed(HeapWord* blk_start, HeapWord* blk_end) { - // Verify that the BOT shows [blk_start, blk_end) to be one block. - verify_single_block(blk_start, blk_end); - // adjust _unallocated_block upward or downward - // as appropriate - if (BlockOffsetArrayUseUnallocatedBlock) { - assert(_unallocated_block <= _end, - "Inconsistent value for _unallocated_block"); - if (blk_end >= _unallocated_block && blk_start <= _unallocated_block) { - // CMS-specific note: a block abutting _unallocated_block to - // its left is being freed, a new block is being added or - // we are resetting following a compaction - _unallocated_block = blk_start; - } - } -} - -inline void G1BlockOffsetArray::freed(HeapWord* blk, size_t size) { - freed(blk, blk + size); -} - #endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1BLOCKOFFSETTABLE_INLINE_HPP
--- a/src/share/vm/gc_implementation/g1/g1CardCounts.cpp Fri Oct 31 21:04:37 2014 +0000 +++ b/src/share/vm/gc_implementation/g1/g1CardCounts.cpp Tue Nov 04 17:16:46 2014 +0000 @@ -33,7 +33,10 @@ PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC -void G1CardCountsMappingChangedListener::on_commit(uint start_idx, size_t num_regions) { +void G1CardCountsMappingChangedListener::on_commit(uint start_idx, size_t num_regions, bool zero_filled) { + if (zero_filled) { + return; + } MemRegion mr(G1CollectedHeap::heap()->bottom_addr_for_region(start_idx), num_regions * HeapRegion::GrainWords); _counts->clear_range(mr); }
--- a/src/share/vm/gc_implementation/g1/g1CardCounts.hpp Fri Oct 31 21:04:37 2014 +0000 +++ b/src/share/vm/gc_implementation/g1/g1CardCounts.hpp Tue Nov 04 17:16:46 2014 +0000 @@ -42,7 +42,7 @@ public: void set_cardcounts(G1CardCounts* counts) { _counts = counts; } - virtual void on_commit(uint start_idx, size_t num_regions); + virtual void on_commit(uint start_idx, size_t num_regions, bool zero_filled); }; // Table to track the number of times a card has been refined. Once
--- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Fri Oct 31 21:04:37 2014 +0000 +++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Tue Nov 04 17:16:46 2014 +0000 @@ -385,7 +385,9 @@ OtherRegionsTable::invalidate(start_idx, num_regions); } -void G1RegionMappingChangedListener::on_commit(uint start_idx, size_t num_regions) { +void G1RegionMappingChangedListener::on_commit(uint start_idx, size_t num_regions, bool zero_filled) { + // The from card cache is not the memory that is actually committed. So we cannot + // take advantage of the zero_filled parameter. reset_from_card_cache(start_idx, num_regions); } @@ -2343,6 +2345,7 @@ case GCCause::_gc_locker: return GCLockerInvokesConcurrent; case GCCause::_java_lang_system_gc: return ExplicitGCInvokesConcurrent; case GCCause::_g1_humongous_allocation: return true; + case GCCause::_update_allocation_context_stats_inc: return true; default: return false; } }
--- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp Fri Oct 31 21:04:37 2014 +0000 +++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp Tue Nov 04 17:16:46 2014 +0000 @@ -172,7 +172,7 @@ private: void reset_from_card_cache(uint start_idx, size_t num_regions); public: - virtual void on_commit(uint start_idx, size_t num_regions); + virtual void on_commit(uint start_idx, size_t num_regions, bool zero_filled); }; class G1CollectedHeap : public SharedHeap {
--- a/src/share/vm/gc_implementation/g1/g1RegionToSpaceMapper.cpp Fri Oct 31 21:04:37 2014 +0000 +++ b/src/share/vm/gc_implementation/g1/g1RegionToSpaceMapper.cpp Tue Nov 04 17:16:46 2014 +0000 @@ -69,7 +69,7 @@ virtual void commit_regions(uintptr_t start_idx, size_t num_regions) { _storage.commit(start_idx * _pages_per_region, num_regions * _pages_per_region); _commit_map.set_range(start_idx, start_idx + num_regions); - fire_on_commit(start_idx, num_regions); + fire_on_commit(start_idx, num_regions, true); } virtual void uncommit_regions(uintptr_t start_idx, size_t num_regions) { @@ -115,12 +115,14 @@ assert(!_commit_map.at(i), err_msg("Trying to commit storage at region "INTPTR_FORMAT" that is already committed", i)); uintptr_t idx = region_idx_to_page_idx(i); uint old_refcount = _refcounts.get_by_index(idx); + bool zero_filled = false; if (old_refcount == 0) { _storage.commit(idx, 1); + zero_filled = true; } _refcounts.set_by_index(idx, old_refcount + 1); _commit_map.set_bit(i); - fire_on_commit(i, 1); + fire_on_commit(i, 1, zero_filled); } } @@ -139,9 +141,9 @@ } }; -void G1RegionToSpaceMapper::fire_on_commit(uint start_idx, size_t num_regions) { +void G1RegionToSpaceMapper::fire_on_commit(uint start_idx, size_t num_regions, bool zero_filled) { if (_listener != NULL) { - _listener->on_commit(start_idx, num_regions); + _listener->on_commit(start_idx, num_regions, zero_filled); } }
--- a/src/share/vm/gc_implementation/g1/g1RegionToSpaceMapper.hpp Fri Oct 31 21:04:37 2014 +0000 +++ b/src/share/vm/gc_implementation/g1/g1RegionToSpaceMapper.hpp Tue Nov 04 17:16:46 2014 +0000 @@ -33,7 +33,9 @@ public: // Fired after commit of the memory, i.e. the memory this listener is registered // for can be accessed. - virtual void on_commit(uint start_idx, size_t num_regions) = 0; + // Zero_filled indicates that the memory can be considered as filled with zero bytes + // when called. + virtual void on_commit(uint start_idx, size_t num_regions, bool zero_filled) = 0; }; // Maps region based commit/uncommit requests to the underlying page sized virtual @@ -51,7 +53,7 @@ G1RegionToSpaceMapper(ReservedSpace rs, size_t commit_granularity, size_t region_granularity, MemoryType type); - void fire_on_commit(uint start_idx, size_t num_regions); + void fire_on_commit(uint start_idx, size_t num_regions, bool zero_filled); public: MemRegion reserved() { return _storage.reserved(); }
--- a/src/share/vm/gc_implementation/g1/g1SATBCardTableModRefBS.cpp Fri Oct 31 21:04:37 2014 +0000 +++ b/src/share/vm/gc_implementation/g1/g1SATBCardTableModRefBS.cpp Tue Nov 04 17:16:46 2014 +0000 @@ -124,7 +124,8 @@ } #endif -void G1SATBCardTableLoggingModRefBSChangedListener::on_commit(uint start_idx, size_t num_regions) { +void G1SATBCardTableLoggingModRefBSChangedListener::on_commit(uint start_idx, size_t num_regions, bool zero_filled) { + // Default value for a clean card on the card table is -1. So we cannot take advantage of the zero_filled parameter. MemRegion mr(G1CollectedHeap::heap()->bottom_addr_for_region(start_idx), num_regions * HeapRegion::GrainWords); _card_table->clear(mr); }
--- a/src/share/vm/gc_implementation/g1/g1SATBCardTableModRefBS.hpp Fri Oct 31 21:04:37 2014 +0000 +++ b/src/share/vm/gc_implementation/g1/g1SATBCardTableModRefBS.hpp Tue Nov 04 17:16:46 2014 +0000 @@ -136,7 +136,7 @@ void set_card_table(G1SATBCardTableLoggingModRefBS* card_table) { _card_table = card_table; } - virtual void on_commit(uint start_idx, size_t num_regions); + virtual void on_commit(uint start_idx, size_t num_regions, bool zero_filled); }; // Adds card-table logging to the post-barrier.
--- a/src/share/vm/gc_implementation/g1/g1_globals.hpp Fri Oct 31 21:04:37 2014 +0000 +++ b/src/share/vm/gc_implementation/g1/g1_globals.hpp Tue Nov 04 17:16:46 2014 +0000 @@ -270,12 +270,12 @@ "Percentage (0-100) of the heap size to use as default " \ " maximum young gen size.") \ \ - experimental(uintx, G1MixedGCLiveThresholdPercent, 65, \ + experimental(uintx, G1MixedGCLiveThresholdPercent, 85, \ "Threshold for regions to be considered for inclusion in the " \ "collection set of mixed GCs. " \ "Regions with live bytes exceeding this will not be collected.") \ \ - product(uintx, G1HeapWastePercent, 10, \ + product(uintx, G1HeapWastePercent, 5, \ "Amount of space, expressed as a percentage of the heap size, " \ "that G1 is willing not to collect to avoid expensive GCs.") \ \
--- a/src/share/vm/gc_implementation/g1/heapRegion.cpp Fri Oct 31 21:04:37 2014 +0000 +++ b/src/share/vm/gc_implementation/g1/heapRegion.cpp Tue Nov 04 17:16:46 2014 +0000 @@ -304,29 +304,6 @@ return false; } -HeapWord* HeapRegion::next_block_start_careful(HeapWord* addr) { - HeapWord* low = addr; - HeapWord* high = end(); - while (low < high) { - size_t diff = pointer_delta(high, low); - // Must add one below to bias toward the high amount. Otherwise, if - // "high" were at the desired value, and "low" were one less, we - // would not converge on "high". This is not symmetric, because - // we set "high" to a block start, which might be the right one, - // which we don't do for "low". - HeapWord* middle = low + (diff+1)/2; - if (middle == high) return high; - HeapWord* mid_bs = block_start_careful(middle); - if (mid_bs < addr) { - low = middle; - } else { - high = mid_bs; - } - } - assert(low == high && low >= addr, "Didn't work."); - return low; -} - HeapRegion::HeapRegion(uint hrm_index, G1BlockOffsetSharedArray* sharedOffsetArray, MemRegion mr) :
--- a/src/share/vm/gc_implementation/g1/heapRegion.hpp Fri Oct 31 21:04:37 2014 +0000 +++ b/src/share/vm/gc_implementation/g1/heapRegion.hpp Tue Nov 04 17:16:46 2014 +0000 @@ -203,10 +203,6 @@ _offsets.reset_bot(); } - void update_bot_for_object(HeapWord* start, size_t word_size) { - _offsets.alloc_block(start, word_size); - } - void print_bot_on(outputStream* out) { _offsets.print_on(out); } @@ -737,18 +733,6 @@ bool filter_young, jbyte* card_ptr); - // A version of block start that is guaranteed to find *some* block - // boundary at or before "p", but does not object iteration, and may - // therefore be used safely when the heap is unparseable. - HeapWord* block_start_careful(const void* p) const { - return _offsets.block_start_careful(p); - } - - // Requires that "addr" is within the region. Returns the start of the - // first ("careful") block that starts at or after "addr", or else the - // "end" of the region if there is no such block. - HeapWord* next_block_start_careful(HeapWord* addr); - size_t recorded_rs_length() const { return _recorded_rs_length; } double predicted_elapsed_time_ms() const { return _predicted_elapsed_time_ms; } size_t predicted_bytes_to_copy() const { return _predicted_bytes_to_copy; }
--- a/src/share/vm/gc_implementation/g1/vm_operations_g1.cpp Fri Oct 31 21:04:37 2014 +0000 +++ b/src/share/vm/gc_implementation/g1/vm_operations_g1.cpp Tue Nov 04 17:16:46 2014 +0000 @@ -95,8 +95,9 @@ assert(!_should_initiate_conc_mark || ((_gc_cause == GCCause::_gc_locker && GCLockerInvokesConcurrent) || (_gc_cause == GCCause::_java_lang_system_gc && ExplicitGCInvokesConcurrent) || - _gc_cause == GCCause::_g1_humongous_allocation), - "only a GC locker, a System.gc() or a hum allocation induced GC should start a cycle"); + _gc_cause == GCCause::_g1_humongous_allocation || + _gc_cause == GCCause::_update_allocation_context_stats_inc), + "only a GC locker, a System.gc(), stats update or a hum allocation induced GC should start a cycle"); if (_word_size > 0) { // An allocation has been requested. So, try to do that first.
--- a/src/share/vm/gc_interface/gcCause.cpp Fri Oct 31 21:04:37 2014 +0000 +++ b/src/share/vm/gc_interface/gcCause.cpp Tue Nov 04 17:16:46 2014 +0000 @@ -54,7 +54,8 @@ case _wb_young_gc: return "WhiteBox Initiated Young GC"; - case _update_allocation_context_stats: + case _update_allocation_context_stats_inc: + case _update_allocation_context_stats_full: return "Update Allocation Context Stats"; case _no_gc:
--- a/src/share/vm/gc_interface/gcCause.hpp Fri Oct 31 21:04:37 2014 +0000 +++ b/src/share/vm/gc_interface/gcCause.hpp Tue Nov 04 17:16:46 2014 +0000 @@ -47,7 +47,8 @@ _heap_inspection, _heap_dump, _wb_young_gc, - _update_allocation_context_stats, + _update_allocation_context_stats_inc, + _update_allocation_context_stats_full, /* implementation independent, but reserved for GC use */ _no_gc,
--- a/src/share/vm/interpreter/linkResolver.cpp Fri Oct 31 21:04:37 2014 +0000 +++ b/src/share/vm/interpreter/linkResolver.cpp Tue Nov 04 17:16:46 2014 +0000 @@ -246,6 +246,12 @@ // Ignore overpasses so statics can be found during resolution Method* result_oop = klass->uncached_lookup_method(name, signature, Klass::skip_overpass); + if (klass->oop_is_array()) { + // Only consider klass and super klass for arrays + result = methodHandle(THREAD, result_oop); + return; + } + // JDK 8, JVMS 5.4.3.4: Interface method resolution should // ignore static and non-public methods of java.lang.Object, // like clone, finalize, registerNatives. @@ -290,6 +296,11 @@ result = methodHandle(THREAD, super_klass->uncached_lookup_method(name, signature, Klass::normal)); } + if (klass->oop_is_array()) { + // Only consider klass and super klass for arrays + return; + } + if (result.is_null()) { Array<Method*>* default_methods = InstanceKlass::cast(klass())->default_methods(); if (default_methods != NULL) { @@ -546,7 +557,7 @@ // 2. lookup method in resolved klass and its super klasses lookup_method_in_klasses(resolved_method, resolved_klass, method_name, method_signature, true, false, CHECK); - if (resolved_method.is_null()) { // not found in the class hierarchy + if (resolved_method.is_null() && !resolved_klass->oop_is_array()) { // not found in the class hierarchy // 3. lookup method in all the interfaces implemented by the resolved klass lookup_method_in_interfaces(resolved_method, resolved_klass, method_name, method_signature, CHECK); @@ -559,16 +570,16 @@ CLEAR_PENDING_EXCEPTION; } } + } - if (resolved_method.is_null()) { - // 4. method lookup failed - ResourceMark rm(THREAD); - THROW_MSG_CAUSE(vmSymbols::java_lang_NoSuchMethodError(), - Method::name_and_sig_as_C_string(resolved_klass(), - method_name, - method_signature), - nested_exception); - } + if (resolved_method.is_null()) { + // 4. method lookup failed + ResourceMark rm(THREAD); + THROW_MSG_CAUSE(vmSymbols::java_lang_NoSuchMethodError(), + Method::name_and_sig_as_C_string(resolved_klass(), + method_name, + method_signature), + nested_exception); } // 5. access checks, access checking may be turned off when calling from within the VM. @@ -634,17 +645,18 @@ // JDK8: also look for static methods lookup_method_in_klasses(resolved_method, resolved_klass, method_name, method_signature, false, true, CHECK); - if (resolved_method.is_null()) { + if (resolved_method.is_null() && !resolved_klass->oop_is_array()) { // lookup method in all the super-interfaces lookup_method_in_interfaces(resolved_method, resolved_klass, method_name, method_signature, CHECK); - if (resolved_method.is_null()) { - // no method found - ResourceMark rm(THREAD); - THROW_MSG(vmSymbols::java_lang_NoSuchMethodError(), - Method::name_and_sig_as_C_string(resolved_klass(), - method_name, - method_signature)); - } + } + + if (resolved_method.is_null()) { + // no method found + ResourceMark rm(THREAD); + THROW_MSG(vmSymbols::java_lang_NoSuchMethodError(), + Method::name_and_sig_as_C_string(resolved_klass(), + method_name, + method_signature)); } if (check_access) { @@ -776,7 +788,7 @@ } // Resolve instance field - KlassHandle sel_klass(THREAD, InstanceKlass::cast(resolved_klass())->find_field(field, sig, &fd)); + KlassHandle sel_klass(THREAD, resolved_klass->find_field(field, sig, &fd)); // check if field exists; i.e., if a klass containing the field def has been selected if (sel_klass.is_null()) { ResourceMark rm(THREAD);
--- a/src/share/vm/memory/filemap.cpp Fri Oct 31 21:04:37 2014 +0000 +++ b/src/share/vm/memory/filemap.cpp Tue Nov 04 17:16:46 2014 +0000 @@ -314,7 +314,6 @@ fail_continue("The shared archive file has the wrong version."); return false; } - _file_offset = (long)n; size_t info_size = _header->_paths_misc_info_size; _paths_misc_info = NEW_C_HEAP_ARRAY_RETURN_NULL(char, info_size, mtClass); @@ -330,6 +329,14 @@ return false; } + size_t len = lseek(fd, 0, SEEK_END); + struct FileMapInfo::FileMapHeader::space_info* si = + &_header->_space[MetaspaceShared::mc]; + if (si->_file_offset >= len || len - si->_file_offset < si->_used) { + fail_continue("The shared archive file has been truncated."); + return false; + } + _file_offset += (long)n; return true; } @@ -430,6 +437,7 @@ si->_capacity = capacity; si->_read_only = read_only; si->_allow_exec = allow_exec; + si->_crc = ClassLoader::crc32(0, base, (jint)size); write_bytes_aligned(base, (int)size); } @@ -454,14 +462,15 @@ // Align file position to an allocation unit boundary. void FileMapInfo::align_file_position() { - long new_file_offset = align_size_up(_file_offset, os::vm_allocation_granularity()); + size_t new_file_offset = align_size_up(_file_offset, + os::vm_allocation_granularity()); if (new_file_offset != _file_offset) { _file_offset = new_file_offset; if (_file_open) { // Seek one byte back from the target and write a byte to insure // that the written file is the correct length. _file_offset -= 1; - if (lseek(_fd, _file_offset, SEEK_SET) < 0) { + if (lseek(_fd, (long)_file_offset, SEEK_SET) < 0) { fail_stop("Unable to seek.", NULL); } char zero = 0; @@ -568,6 +577,19 @@ return base; } +bool FileMapInfo::verify_region_checksum(int i) { + if (!VerifySharedSpaces) { + return true; + } + const char* buf = _header->_space[i]._base; + size_t sz = _header->_space[i]._used; + int crc = ClassLoader::crc32(0, buf, (jint)sz); + if (crc != _header->_space[i]._crc) { + fail_continue("Checksum verification failed."); + return false; + } + return true; +} // Unmap a memory region in the address space. @@ -628,13 +650,31 @@ return true; } +int FileMapInfo::FileMapHeader::compute_crc() { + char* header = data(); + // start computing from the field after _crc + char* buf = (char*)&_crc + sizeof(int); + size_t sz = data_size() - (buf - header); + int crc = ClassLoader::crc32(0, buf, (jint)sz); + return crc; +} + +int FileMapInfo::compute_header_crc() { + return _header->compute_crc(); +} + bool FileMapInfo::FileMapHeader::validate() { + if (_magic != (int)0xf00baba2) { + FileMapInfo::fail_continue("The shared archive file has a bad magic number."); + return false; + } + if (VerifySharedSpaces && compute_crc() != _crc) { + fail_continue("Header checksum verification failed."); + return false; + } if (_version != current_version()) { FileMapInfo::fail_continue("The shared archive file is the wrong version."); - return false; - } - if (_magic != (int)0xf00baba2) { - FileMapInfo::fail_continue("The shared archive file has a bad magic number."); + return false; } char header_version[JVM_IDENT_MAX];
--- a/src/share/vm/memory/filemap.hpp Fri Oct 31 21:04:37 2014 +0000 +++ b/src/share/vm/memory/filemap.hpp Tue Nov 04 17:16:46 2014 +0000 @@ -61,7 +61,7 @@ bool _file_open; int _fd; - long _file_offset; + size_t _file_offset; private: static SharedClassPathEntry* _classpath_entry_table; @@ -87,12 +87,14 @@ } int _magic; // identify file type. + int _crc; // header crc checksum. int _version; // (from enum, above.) size_t _alignment; // how shared archive should be aligned int _obj_alignment; // value of ObjectAlignmentInBytes struct space_info { - int _file_offset; // sizeof(this) rounded to vm page size + int _crc; // crc checksum of the current space + size_t _file_offset; // sizeof(this) rounded to vm page size char* _base; // copy-on-write base address size_t _capacity; // for validity checking size_t _used; // for setting space top on read @@ -135,6 +137,7 @@ virtual bool validate(); virtual void populate(FileMapInfo* info, size_t alignment); + int compute_crc(); }; FileMapHeader * _header; @@ -153,6 +156,8 @@ ~FileMapInfo(); static int current_version() { return _current_version; } + int compute_header_crc(); + void set_header_crc(int crc) { _header->_crc = crc; } void populate_header(size_t alignment); bool validate_header(); void invalidate(); @@ -181,6 +186,7 @@ void write_bytes_aligned(const void* buffer, int count); char* map_region(int i); void unmap_region(int i); + bool verify_region_checksum(int i); void close(); bool is_open() { return _file_open; } ReservedSpace reserve_shared_memory();
--- a/src/share/vm/memory/metaspace.cpp Fri Oct 31 21:04:37 2014 +0000 +++ b/src/share/vm/memory/metaspace.cpp Tue Nov 04 17:16:46 2014 +0000 @@ -1414,10 +1414,31 @@ return value; } -size_t MetaspaceGC::inc_capacity_until_GC(size_t v) { +bool MetaspaceGC::inc_capacity_until_GC(size_t v, size_t* new_cap_until_GC, size_t* old_cap_until_GC) { assert_is_size_aligned(v, Metaspace::commit_alignment()); - return (size_t)Atomic::add_ptr(v, &_capacity_until_GC); + size_t capacity_until_GC = (size_t) _capacity_until_GC; + size_t new_value = capacity_until_GC + v; + + if (new_value < capacity_until_GC) { + // The addition wrapped around, set new_value to aligned max value. + new_value = align_size_down(max_uintx, Metaspace::commit_alignment()); + } + + intptr_t expected = (intptr_t) capacity_until_GC; + intptr_t actual = Atomic::cmpxchg_ptr((intptr_t) new_value, &_capacity_until_GC, expected); + + if (expected != actual) { + return false; + } + + if (new_cap_until_GC != NULL) { + *new_cap_until_GC = new_value; + } + if (old_cap_until_GC != NULL) { + *old_cap_until_GC = capacity_until_GC; + } + return true; } size_t MetaspaceGC::dec_capacity_until_GC(size_t v) { @@ -1517,7 +1538,10 @@ expand_bytes = align_size_up(expand_bytes, Metaspace::commit_alignment()); // Don't expand unless it's significant if (expand_bytes >= MinMetaspaceExpansion) { - size_t new_capacity_until_GC = MetaspaceGC::inc_capacity_until_GC(expand_bytes); + size_t new_capacity_until_GC = 0; + bool succeeded = MetaspaceGC::inc_capacity_until_GC(expand_bytes, &new_capacity_until_GC); + assert(succeeded, "Should always succesfully increment HWM when at safepoint"); + Metaspace::tracer()->report_gc_threshold(capacity_until_GC, new_capacity_until_GC, MetaspaceGCThresholdUpdater::ComputeNewSize); @@ -3359,19 +3383,29 @@ size_t delta_bytes = MetaspaceGC::delta_capacity_until_GC(word_size * BytesPerWord); assert(delta_bytes > 0, "Must be"); - size_t after_inc = MetaspaceGC::inc_capacity_until_GC(delta_bytes); - - // capacity_until_GC might be updated concurrently, must calculate previous value. - size_t before_inc = after_inc - delta_bytes; - - tracer()->report_gc_threshold(before_inc, after_inc, - MetaspaceGCThresholdUpdater::ExpandAndAllocate); - if (PrintGCDetails && Verbose) { - gclog_or_tty->print_cr("Increase capacity to GC from " SIZE_FORMAT - " to " SIZE_FORMAT, before_inc, after_inc); + size_t before = 0; + size_t after = 0; + MetaWord* res; + bool incremented; + + // Each thread increments the HWM at most once. Even if the thread fails to increment + // the HWM, an allocation is still attempted. This is because another thread must then + // have incremented the HWM and therefore the allocation might still succeed. + do { + incremented = MetaspaceGC::inc_capacity_until_GC(delta_bytes, &after, &before); + res = allocate(word_size, mdtype); + } while (!incremented && res == NULL); + + if (incremented) { + tracer()->report_gc_threshold(before, after, + MetaspaceGCThresholdUpdater::ExpandAndAllocate); + if (PrintGCDetails && Verbose) { + gclog_or_tty->print_cr("Increase capacity to GC from " SIZE_FORMAT + " to " SIZE_FORMAT, before, after); + } } - return allocate(word_size, mdtype); + return res; } // Space allocated in the Metaspace. This may
--- a/src/share/vm/memory/metaspace.hpp Fri Oct 31 21:04:37 2014 +0000 +++ b/src/share/vm/memory/metaspace.hpp Tue Nov 04 17:16:46 2014 +0000 @@ -404,7 +404,9 @@ static void post_initialize(); static size_t capacity_until_GC(); - static size_t inc_capacity_until_GC(size_t v); + static bool inc_capacity_until_GC(size_t v, + size_t* new_cap_until_GC = NULL, + size_t* old_cap_until_GC = NULL); static size_t dec_capacity_until_GC(size_t v); static bool should_concurrent_collect() { return _should_concurrent_collect; }
--- a/src/share/vm/memory/metaspaceShared.cpp Fri Oct 31 21:04:37 2014 +0000 +++ b/src/share/vm/memory/metaspaceShared.cpp Tue Nov 04 17:16:46 2014 +0000 @@ -607,6 +607,7 @@ // Pass 2 - write data. mapinfo->open_for_write(); + mapinfo->set_header_crc(mapinfo->compute_header_crc()); mapinfo->write_header(); mapinfo->write_space(MetaspaceShared::ro, _loader_data->ro_metaspace(), true); mapinfo->write_space(MetaspaceShared::rw, _loader_data->rw_metaspace(), false); @@ -936,9 +937,13 @@ // Map each shared region if ((_ro_base = mapinfo->map_region(ro)) != NULL && + mapinfo->verify_region_checksum(ro) && (_rw_base = mapinfo->map_region(rw)) != NULL && + mapinfo->verify_region_checksum(rw) && (_md_base = mapinfo->map_region(md)) != NULL && + mapinfo->verify_region_checksum(md) && (_mc_base = mapinfo->map_region(mc)) != NULL && + mapinfo->verify_region_checksum(mc) && (image_alignment == (size_t)max_alignment()) && mapinfo->validate_classpath_entry_table()) { // Success (no need to do anything)
--- a/src/share/vm/oops/arrayKlass.cpp Fri Oct 31 21:04:37 2014 +0000 +++ b/src/share/vm/oops/arrayKlass.cpp Tue Nov 04 17:16:46 2014 +0000 @@ -64,6 +64,13 @@ return NULL; } +// find field according to JVM spec 5.4.3.2, returns the klass in which the field is defined +Klass* ArrayKlass::find_field(Symbol* name, Symbol* sig, fieldDescriptor* fd) const { + // There are no fields in an array klass but look to the super class (Object) + assert(super(), "super klass must be present"); + return super()->find_field(name, sig, fd); +} + Method* ArrayKlass::uncached_lookup_method(Symbol* name, Symbol* signature, MethodLookupMode mode) const { // There are no methods in an array klass but the super class (Object) has some assert(super(), "super klass must be present");
--- a/src/share/vm/oops/arrayKlass.hpp Fri Oct 31 21:04:37 2014 +0000 +++ b/src/share/vm/oops/arrayKlass.hpp Tue Nov 04 17:16:46 2014 +0000 @@ -28,6 +28,7 @@ #include "memory/universe.hpp" #include "oops/klass.hpp" +class fieldDescriptor; class klassVtable; // ArrayKlass is the abstract baseclass for all array classes @@ -85,6 +86,9 @@ virtual oop multi_allocate(int rank, jint* sizes, TRAPS); objArrayOop allocate_arrayArray(int n, int length, TRAPS); + // find field according to JVM spec 5.4.3.2, returns the klass in which the field is defined + Klass* find_field(Symbol* name, Symbol* sig, fieldDescriptor* fd) const; + // Lookup operations Method* uncached_lookup_method(Symbol* name, Symbol* signature, MethodLookupMode mode) const;
--- a/src/share/vm/oops/klass.cpp Fri Oct 31 21:04:37 2014 +0000 +++ b/src/share/vm/oops/klass.cpp Tue Nov 04 17:16:46 2014 +0000 @@ -130,6 +130,15 @@ return is_subclass_of(k); } +Klass* Klass::find_field(Symbol* name, Symbol* sig, fieldDescriptor* fd) const { +#ifdef ASSERT + tty->print_cr("Error: find_field called on a klass oop." + " Likely error: reflection method does not correctly" + " wrap return value in a mirror object."); +#endif + ShouldNotReachHere(); + return NULL; +} Method* Klass::uncached_lookup_method(Symbol* name, Symbol* signature, MethodLookupMode mode) const { #ifdef ASSERT
--- a/src/share/vm/oops/klass.hpp Fri Oct 31 21:04:37 2014 +0000 +++ b/src/share/vm/oops/klass.hpp Tue Nov 04 17:16:46 2014 +0000 @@ -90,6 +90,7 @@ class klassVtable; class ParCompactionManager; class KlassSizeStats; +class fieldDescriptor; class Klass : public Metadata { friend class VMStructs; @@ -441,6 +442,7 @@ virtual void initialize(TRAPS); // lookup operation for MethodLookupCache friend class MethodLookupCache; + virtual Klass* find_field(Symbol* name, Symbol* signature, fieldDescriptor* fd) const; virtual Method* uncached_lookup_method(Symbol* name, Symbol* signature, MethodLookupMode mode) const; public: Method* lookup_method(Symbol* name, Symbol* signature) const {
--- a/src/share/vm/opto/doCall.cpp Fri Oct 31 21:04:37 2014 +0000 +++ b/src/share/vm/opto/doCall.cpp Tue Nov 04 17:16:46 2014 +0000 @@ -799,10 +799,16 @@ // each arm of the Phi. If I know something clever about the exceptions // I'm loading the class from, I can replace the LoadKlass with the // klass constant for the exception oop. - if( ex_node->is_Phi() ) { - ex_klass_node = new (C) PhiNode( ex_node->in(0), TypeKlassPtr::OBJECT ); - for( uint i = 1; i < ex_node->req(); i++ ) { - Node* p = basic_plus_adr( ex_node->in(i), ex_node->in(i), oopDesc::klass_offset_in_bytes() ); + if (ex_node->is_Phi()) { + ex_klass_node = new (C) PhiNode(ex_node->in(0), TypeKlassPtr::OBJECT); + for (uint i = 1; i < ex_node->req(); i++) { + Node* ex_in = ex_node->in(i); + if (ex_in == top() || ex_in == NULL) { + // This path was not taken. + ex_klass_node->init_req(i, top()); + continue; + } + Node* p = basic_plus_adr(ex_in, ex_in, oopDesc::klass_offset_in_bytes()); Node* k = _gvn.transform( LoadKlassNode::make(_gvn, immutable_memory(), p, TypeInstPtr::KLASS, TypeKlassPtr::OBJECT) ); ex_klass_node->init_req( i, k ); }
--- a/src/share/vm/prims/jvm.cpp Fri Oct 31 21:04:37 2014 +0000 +++ b/src/share/vm/prims/jvm.cpp Tue Nov 04 17:16:46 2014 +0000 @@ -808,6 +808,7 @@ return (jclass) JNIHandles::make_local(env, k->java_mirror()); JVM_END +// Not used; JVM_FindClassFromCaller replaces this. JVM_ENTRY(jclass, JVM_FindClassFromClassLoader(JNIEnv* env, const char* name, jboolean init, jobject loader, jboolean throwError)) @@ -834,6 +835,42 @@ return result; JVM_END +// Find a class with this name in this loader, using the caller's protection domain. +JVM_ENTRY(jclass, JVM_FindClassFromCaller(JNIEnv* env, const char* name, + jboolean init, jobject loader, + jclass caller)) + JVMWrapper2("JVM_FindClassFromCaller %s throws ClassNotFoundException", name); + // Java libraries should ensure that name is never null... + if (name == NULL || (int)strlen(name) > Symbol::max_length()) { + // It's impossible to create this class; the name cannot fit + // into the constant pool. + THROW_MSG_0(vmSymbols::java_lang_ClassNotFoundException(), name); + } + + TempNewSymbol h_name = SymbolTable::new_symbol(name, CHECK_NULL); + + oop loader_oop = JNIHandles::resolve(loader); + oop from_class = JNIHandles::resolve(caller); + oop protection_domain = NULL; + // If loader is null, shouldn't call ClassLoader.checkPackageAccess; otherwise get + // NPE. Put it in another way, the bootstrap class loader has all permission and + // thus no checkPackageAccess equivalence in the VM class loader. + // The caller is also passed as NULL by the java code if there is no security + // manager to avoid the performance cost of getting the calling class. + if (from_class != NULL && loader_oop != NULL) { + protection_domain = java_lang_Class::as_Klass(from_class)->protection_domain(); + } + + Handle h_loader(THREAD, loader_oop); + Handle h_prot(THREAD, protection_domain); + jclass result = find_class_from_class_loader(env, h_name, init, h_loader, + h_prot, false, THREAD); + + if (TraceClassResolution && result != NULL) { + trace_class_resolution(java_lang_Class::as_Klass(JNIHandles::resolve_non_null(result))); + } + return result; +JVM_END JVM_ENTRY(jclass, JVM_FindClassFromClass(JNIEnv *env, const char *name, jboolean init, jclass from)) @@ -4007,10 +4044,15 @@ // Shared JNI/JVM entry points ////////////////////////////////////////////////////////////// -jclass find_class_from_class_loader(JNIEnv* env, Symbol* name, jboolean init, Handle loader, Handle protection_domain, jboolean throwError, TRAPS) { +jclass find_class_from_class_loader(JNIEnv* env, Symbol* name, jboolean init, + Handle loader, Handle protection_domain, + jboolean throwError, TRAPS) { // Security Note: // The Java level wrapper will perform the necessary security check allowing - // us to pass the NULL as the initiating class loader. + // us to pass the NULL as the initiating class loader. The VM is responsible for + // the checkPackageAccess relative to the initiating class loader via the + // protection_domain. The protection_domain is passed as NULL by the java code + // if there is no security manager in 3-arg Class.forName(). Klass* klass = SystemDictionary::resolve_or_fail(name, loader, protection_domain, throwError != 0, CHECK_NULL); KlassHandle klass_handle(THREAD, klass);
--- a/src/share/vm/prims/jvm.h Fri Oct 31 21:04:37 2014 +0000 +++ b/src/share/vm/prims/jvm.h Tue Nov 04 17:16:46 2014 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2014, 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 @@ -420,6 +420,19 @@ JVM_FindClassFromBootLoader(JNIEnv *env, const char *name); /* + * Find a class from a given class loader. Throws ClassNotFoundException. + * name: name of class + * init: whether initialization is done + * loader: class loader to look up the class. This may not be the same as the caller's + * class loader. + * caller: initiating class. The initiating class may be null when a security + * manager is not installed. + */ +JNIEXPORT jclass JNICALL +JVM_FindClassFromCaller(JNIEnv *env, const char *name, jboolean init, + jobject loader, jclass caller); + +/* * Find a class from a given class. */ JNIEXPORT jclass JNICALL
--- a/src/share/vm/prims/whitebox.cpp Fri Oct 31 21:04:37 2014 +0000 +++ b/src/share/vm/prims/whitebox.cpp Tue Nov 04 17:16:46 2014 +0000 @@ -331,7 +331,36 @@ } WB_END +WB_ENTRY(jboolean, WB_NMTChangeTrackingLevel(JNIEnv* env)) + // Test that we can downgrade NMT levels but not upgrade them. + if (MemTracker::tracking_level() == NMT_off) { + MemTracker::transition_to(NMT_off); + return MemTracker::tracking_level() == NMT_off; + } else { + assert(MemTracker::tracking_level() == NMT_detail, "Should start out as detail tracking"); + MemTracker::transition_to(NMT_summary); + assert(MemTracker::tracking_level() == NMT_summary, "Should be summary now"); + // Can't go to detail once NMT is set to summary. + MemTracker::transition_to(NMT_detail); + assert(MemTracker::tracking_level() == NMT_summary, "Should still be summary now"); + + // Shutdown sets tracking level to minimal. + MemTracker::shutdown(); + assert(MemTracker::tracking_level() == NMT_minimal, "Should be minimal now"); + + // Once the tracking level is minimal, we cannot increase to summary. + // The code ignores this request instead of asserting because if the malloc site + // table overflows in another thread, it tries to change the code to summary. + MemTracker::transition_to(NMT_summary); + assert(MemTracker::tracking_level() == NMT_minimal, "Should still be minimal now"); + + // Really can never go up to detail, verify that the code would never do this. + MemTracker::transition_to(NMT_detail); + assert(MemTracker::tracking_level() == NMT_minimal, "Should still be minimal now"); + return MemTracker::tracking_level() == NMT_minimal; + } +WB_END #endif // INCLUDE_NMT static jmethodID reflected_method_to_jmid(JavaThread* thread, JNIEnv* env, jobject method) { @@ -794,6 +823,33 @@ MetadataFactory::free_array(cld, (Array<u1>*)(uintptr_t)addr); WB_END +WB_ENTRY(jlong, WB_IncMetaspaceCapacityUntilGC(JNIEnv* env, jobject wb, jlong inc)) + if (inc < 0) { + THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), + err_msg("WB_IncMetaspaceCapacityUntilGC: inc is negative: " JLONG_FORMAT, inc)); + } + + jlong max_size_t = (jlong) ((size_t) -1); + if (inc > max_size_t) { + THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), + err_msg("WB_IncMetaspaceCapacityUntilGC: inc does not fit in size_t: " JLONG_FORMAT, inc)); + } + + size_t new_cap_until_GC = 0; + size_t aligned_inc = align_size_down((size_t) inc, Metaspace::commit_alignment()); + bool success = MetaspaceGC::inc_capacity_until_GC(aligned_inc, &new_cap_until_GC); + if (!success) { + THROW_MSG_0(vmSymbols::java_lang_IllegalStateException(), + "WB_IncMetaspaceCapacityUntilGC: could not increase capacity until GC " + "due to contention with another thread"); + } + return (jlong) new_cap_until_GC; +WB_END + +WB_ENTRY(jlong, WB_MetaspaceCapacityUntilGC(JNIEnv* env, jobject wb)) + return (jlong) MetaspaceGC::capacity_until_GC(); +WB_END + //Some convenience methods to deal with objects from java int WhiteBox::offset_for_field(const char* field_name, oop object, Symbol* signature_symbol) { @@ -909,6 +965,7 @@ {CC"NMTReleaseMemory", CC"(JJ)V", (void*)&WB_NMTReleaseMemory }, {CC"NMTOverflowHashBucket", CC"(J)V", (void*)&WB_NMTOverflowHashBucket}, {CC"NMTIsDetailSupported",CC"()Z", (void*)&WB_NMTIsDetailSupported}, + {CC"NMTChangeTrackingLevel", CC"()Z", (void*)&WB_NMTChangeTrackingLevel}, #endif // INCLUDE_NMT {CC"deoptimizeAll", CC"()V", (void*)&WB_DeoptimizeAll }, {CC"deoptimizeMethod", CC"(Ljava/lang/reflect/Executable;Z)I", @@ -962,6 +1019,8 @@ CC"(Ljava/lang/ClassLoader;J)J", (void*)&WB_AllocateMetaspace }, {CC"freeMetaspace", CC"(Ljava/lang/ClassLoader;JJ)V", (void*)&WB_FreeMetaspace }, + {CC"incMetaspaceCapacityUntilGC", CC"(J)J", (void*)&WB_IncMetaspaceCapacityUntilGC }, + {CC"metaspaceCapacityUntilGC", CC"()J", (void*)&WB_MetaspaceCapacityUntilGC }, {CC"getCPUFeatures", CC"()Ljava/lang/String;", (void*)&WB_GetCPUFeatures }, {CC"getNMethod", CC"(Ljava/lang/reflect/Executable;Z)[Ljava/lang/Object;", (void*)&WB_GetNMethod },
--- a/src/share/vm/runtime/arguments.cpp Fri Oct 31 21:04:37 2014 +0000 +++ b/src/share/vm/runtime/arguments.cpp Tue Nov 04 17:16:46 2014 +0000 @@ -2390,6 +2390,9 @@ status = status && verify_percentage(MarkSweepDeadRatio, "MarkSweepDeadRatio"); status = status && verify_min_value(MarkSweepAlwaysCompactCount, 1, "MarkSweepAlwaysCompactCount"); +#ifdef COMPILER1 + status = status && verify_min_value(ValueMapInitialSize, 1, "ValueMapInitialSize"); +#endif if (PrintNMTStatistics) { #if INCLUDE_NMT @@ -2455,6 +2458,10 @@ warning("The VM option CICompilerCountPerCPU overrides CICompilerCount."); } +#ifdef COMPILER1 + status &= verify_interval(SafepointPollOffset, 0, os::vm_page_size() - BytesPerWord, "SafepointPollOffset"); +#endif + return status; } @@ -3708,6 +3715,11 @@ return JNI_ENOMEM; } + // Set up VerifySharedSpaces + if (FLAG_IS_DEFAULT(VerifySharedSpaces) && SharedArchiveFile != NULL) { + VerifySharedSpaces = true; + } + // Delay warning until here so that we've had a chance to process // the -XX:-PrintWarnings flag if (needs_hotspotrc_warning) {
--- a/src/share/vm/runtime/globals.hpp Fri Oct 31 21:04:37 2014 +0000 +++ b/src/share/vm/runtime/globals.hpp Tue Nov 04 17:16:46 2014 +0000 @@ -1166,11 +1166,11 @@ "Prevent spurious or premature wakeups from object.wait " \ "(Solaris only)") \ \ - product(intx, NativeMonitorTimeout, -1, "(Unstable)") \ - \ - product(intx, NativeMonitorFlags, 0, "(Unstable)") \ - \ - product(intx, NativeMonitorSpinLimit, 20, "(Unstable)") \ + experimental(intx, NativeMonitorTimeout, -1, "(Unstable)") \ + \ + experimental(intx, NativeMonitorFlags, 0, "(Unstable)") \ + \ + experimental(intx, NativeMonitorSpinLimit, 20, "(Unstable)") \ \ develop(bool, UsePthreads, false, \ "Use pthread-based instead of libthread-based synchronization " \ @@ -3787,6 +3787,10 @@ product(bool, UseSharedSpaces, true, \ "Use shared spaces for metadata") \ \ + product(bool, VerifySharedSpaces, false, \ + "Verify shared spaces (false for default archive, true for " \ + "archive specified by -XX:SharedArchiveFile)") \ + \ product(bool, RequireSharedSpaces, false, \ "Require shared spaces for metadata") \ \
--- a/src/share/vm/runtime/os.hpp Fri Oct 31 21:04:37 2014 +0000 +++ b/src/share/vm/runtime/os.hpp Tue Nov 04 17:16:46 2014 +0000 @@ -214,13 +214,14 @@ // Interface for detecting multiprocessor system static inline bool is_MP() { -#if !INCLUDE_NMT - assert(_processor_count > 0, "invalid processor count"); - return _processor_count > 1 || AssumeMP; -#else - // NMT needs atomic operations before this initialization. - return true; -#endif + // During bootstrap if _processor_count is not yet initialized + // we claim to be MP as that is safest. If any platform has a + // stub generator that might be triggered in this phase and for + // which being declared MP when in fact not, is a problem - then + // the bootstrap routine for the stub generator needs to check + // the processor count directly and leave the bootstrap routine + // in place until called after initialization has ocurred. + return (_processor_count != 1) || AssumeMP; } static julong available_memory(); static julong physical_memory();
--- a/src/share/vm/runtime/reflection.cpp Fri Oct 31 21:04:37 2014 +0000 +++ b/src/share/vm/runtime/reflection.cpp Tue Nov 04 17:16:46 2014 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2014, 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 @@ -484,7 +484,7 @@ ik = InstanceKlass::cast(hc); // There's no way to make a host class loop short of patching memory. - // Therefore there cannot be a loop here unles there's another bug. + // Therefore there cannot be a loop here unless there's another bug. // Still, let's check for it. assert(--inf_loop_check > 0, "no host_klass loop"); } @@ -553,7 +553,8 @@ if (access.is_protected()) { if (!protected_restriction) { // See if current_class (or outermost host class) is a subclass of field_class - if (host_class->is_subclass_of(field_class)) { + // An interface may not access protected members of j.l.Object + if (!host_class->is_interface() && host_class->is_subclass_of(field_class)) { if (access.is_static() || // static fields are ok, see 6622385 current_class == resolved_class || field_class == resolved_class ||
--- a/src/share/vm/services/mallocTracker.cpp Fri Oct 31 21:04:37 2014 +0000 +++ b/src/share/vm/services/mallocTracker.cpp Tue Nov 04 17:16:46 2014 +0000 @@ -51,14 +51,6 @@ return amount; } - -void MallocMemorySnapshot::reset() { - _tracking_header.reset(); - for (int index = 0; index < mt_number_of_types; index ++) { - _malloc[index].reset(); - } -} - // Make adjustment by subtracting chunks used by arenas // from total chunks to get total free chunck size void MallocMemorySnapshot::make_adjustment() { @@ -116,14 +108,9 @@ bool MallocTracker::transition(NMT_TrackingLevel from, NMT_TrackingLevel to) { assert(from != NMT_off, "Can not transition from off state"); assert(to != NMT_off, "Can not transition to off state"); - if (from == NMT_minimal) { - MallocMemorySummary::reset(); - } + assert (from != NMT_minimal, "cannot transition from minimal state"); - if (to == NMT_detail) { - assert(from == NMT_minimal || from == NMT_summary, "Just check"); - return MallocSiteTable::initialize(); - } else if (from == NMT_detail) { + if (from == NMT_detail) { assert(to == NMT_minimal || to == NMT_summary, "Just check"); MallocSiteTable::shutdown(); }
--- a/src/share/vm/services/mallocTracker.hpp Fri Oct 31 21:04:37 2014 +0000 +++ b/src/share/vm/services/mallocTracker.hpp Tue Nov 04 17:16:46 2014 +0000 @@ -51,14 +51,6 @@ DEBUG_ONLY(_peak_size = 0;) } - // Reset counters - void reset() { - _size = 0; - _count = 0; - DEBUG_ONLY(_peak_size = 0;) - DEBUG_ONLY(_peak_count = 0;) - } - inline void allocate(size_t sz) { Atomic::add(1, (volatile MemoryCounterType*)&_count); if (sz > 0) { @@ -124,11 +116,6 @@ _arena.resize(sz); } - void reset() { - _malloc.reset(); - _arena.reset(); - } - inline size_t malloc_size() const { return _malloc.size(); } inline size_t malloc_count() const { return _malloc.count();} inline size_t arena_size() const { return _arena.size(); } @@ -176,8 +163,6 @@ return s->by_type(mtThreadStack)->malloc_count(); } - void reset(); - void copy_to(MallocMemorySnapshot* s) { s->_tracking_header = _tracking_header; for (int index = 0; index < mt_number_of_types; index ++) { @@ -240,11 +225,6 @@ return as_snapshot()->malloc_overhead()->size(); } - // Reset all counters to zero - static void reset() { - as_snapshot()->reset(); - } - static MallocMemorySnapshot* as_snapshot() { return (MallocMemorySnapshot*)_snapshot; }
--- a/src/share/vm/services/memBaseline.hpp Fri Oct 31 21:04:37 2014 +0000 +++ b/src/share/vm/services/memBaseline.hpp Tue Nov 04 17:16:46 2014 +0000 @@ -90,10 +90,6 @@ _class_count(0) { } - ~MemBaseline() { - reset(); - } - bool baseline(bool summaryOnly = true); BaselineType baseline_type() const { return _baseline_type; } @@ -169,8 +165,7 @@ // reset the baseline for reuse void reset() { _baseline_type = Not_baselined; - _malloc_memory_snapshot.reset(); - _virtual_memory_snapshot.reset(); + // _malloc_memory_snapshot and _virtual_memory_snapshot are copied over. _class_count = 0; _malloc_sites.clear();
--- a/src/share/vm/services/memReporter.hpp Fri Oct 31 21:04:37 2014 +0000 +++ b/src/share/vm/services/memReporter.hpp Tue Nov 04 17:16:46 2014 +0000 @@ -96,20 +96,6 @@ size_t _class_count; public: - // Report summary tracking data from global snapshots directly. - // This constructor is used for final reporting and hs_err reporting. - MemSummaryReporter(MallocMemorySnapshot* malloc_snapshot, - VirtualMemorySnapshot* vm_snapshot, outputStream* output, - size_t class_count = 0, size_t scale = K) : - MemReporterBase(output, scale), - _malloc_snapshot(malloc_snapshot), - _vm_snapshot(vm_snapshot) { - if (class_count == 0) { - _class_count = InstanceKlass::number_of_instance_classes(); - } else { - _class_count = class_count; - } - } // This constructor is for normal reporting from a recent baseline. MemSummaryReporter(MemBaseline& baseline, outputStream* output, size_t scale = K) : MemReporterBase(output, scale),
--- a/src/share/vm/services/memTracker.cpp Fri Oct 31 21:04:37 2014 +0000 +++ b/src/share/vm/services/memTracker.cpp Tue Nov 04 17:16:46 2014 +0000 @@ -144,11 +144,9 @@ } -// Shutdown can only be issued via JCmd, and NMT JCmd is serialized -// by lock +// Shutdown can only be issued via JCmd, and NMT JCmd is serialized by lock void MemTracker::shutdown() { - // We can only shutdown NMT to minimal tracking level if it is - // ever on. + // We can only shutdown NMT to minimal tracking level if it is ever on. if (tracking_level () > NMT_minimal) { transition_to(NMT_minimal); } @@ -157,45 +155,36 @@ bool MemTracker::transition_to(NMT_TrackingLevel level) { NMT_TrackingLevel current_level = tracking_level(); + assert(level != NMT_off || current_level == NMT_off, "Cannot transition NMT to off"); + if (current_level == level) { return true; } else if (current_level > level) { - // Downgrade tracking level, we want to lower the tracking - // level first + // Downgrade tracking level, we want to lower the tracking level first _tracking_level = level; // Make _tracking_level visible immediately. OrderAccess::fence(); VirtualMemoryTracker::transition(current_level, level); MallocTracker::transition(current_level, level); - - if (level == NMT_minimal) _baseline.reset(); } else { - VirtualMemoryTracker::transition(current_level, level); - MallocTracker::transition(current_level, level); - - _tracking_level = level; - // Make _tracking_level visible immediately. - OrderAccess::fence(); + // Upgrading tracking level is not supported and has never been supported. + // Allocating and deallocating malloc tracking structures is not thread safe and + // leads to inconsistencies unless a lot coarser locks are added. } - return true; } -void MemTracker::final_report(outputStream* output) { - assert(output != NULL, "No output stream"); - if (tracking_level() >= NMT_summary) { - MallocMemorySnapshot* malloc_memory_snapshot = - MallocMemorySummary::as_snapshot(); - malloc_memory_snapshot->make_adjustment(); - - VirtualMemorySnapshot* virtual_memory_snapshot = - VirtualMemorySummary::as_snapshot(); - - MemSummaryReporter rptr(malloc_memory_snapshot, - virtual_memory_snapshot, output); - rptr.report(); - // shutdown NMT, the data no longer accurate - shutdown(); +void MemTracker::report(bool summary_only, outputStream* output) { + assert(output != NULL, "No output stream"); + MemBaseline baseline; + if (baseline.baseline(summary_only)) { + if (summary_only) { + MemSummaryReporter rpt(baseline, output); + rpt.report(); + } else { + MemDetailReporter rpt(baseline, output); + rpt.report(); + } } }
--- a/src/share/vm/services/memTracker.hpp Fri Oct 31 21:04:37 2014 +0000 +++ b/src/share/vm/services/memTracker.hpp Tue Nov 04 17:16:46 2014 +0000 @@ -70,6 +70,7 @@ static inline void release_thread_stack(void* addr, size_t size) { } static void final_report(outputStream*) { } + static void error_report(outputStream*) { } }; #else @@ -270,13 +271,20 @@ // other tools. static inline Mutex* query_lock() { return _query_lock; } - // Make a final report and shutdown. - // This function generates summary report without creating snapshots, - // to avoid additional memory allocation. It uses native memory summary - // counters, and makes adjustment to them, once the adjustment is made, - // the counters are no longer accurate. As the result, this function - // should only be used for final reporting before shutting down. - static void final_report(outputStream*); + // Make a final report or report for hs_err file. + static void error_report(outputStream* output) { + if (tracking_level() >= NMT_summary) { + report(true, output); // just print summary for error case. + } + } + + static void final_report(outputStream* output) { + NMT_TrackingLevel level = tracking_level(); + if (level >= NMT_summary) { + report(level == NMT_summary, output); + } + } + // Stored baseline static inline MemBaseline& get_baseline() { @@ -291,6 +299,7 @@ private: static NMT_TrackingLevel init_tracking_level(); + static void report(bool summary_only, outputStream* output); private: // Tracking level
--- a/src/share/vm/services/virtualMemoryTracker.cpp Fri Oct 31 21:04:37 2014 +0000 +++ b/src/share/vm/services/virtualMemoryTracker.cpp Tue Nov 04 17:16:46 2014 +0000 @@ -443,26 +443,28 @@ bool VirtualMemoryTracker::walk_virtual_memory(VirtualMemoryWalker* walker) { assert(_reserved_regions != NULL, "Sanity check"); ThreadCritical tc; - LinkedListNode<ReservedMemoryRegion>* head = _reserved_regions->head(); - while (head != NULL) { - const ReservedMemoryRegion* rgn = head->peek(); - if (!walker->do_allocation_site(rgn)) { - return false; + // Check that the _reserved_regions haven't been deleted. + if (_reserved_regions != NULL) { + LinkedListNode<ReservedMemoryRegion>* head = _reserved_regions->head(); + while (head != NULL) { + const ReservedMemoryRegion* rgn = head->peek(); + if (!walker->do_allocation_site(rgn)) { + return false; + } + head = head->next(); } - head = head->next(); - } + } return true; } // Transition virtual memory tracking level. bool VirtualMemoryTracker::transition(NMT_TrackingLevel from, NMT_TrackingLevel to) { - if (from == NMT_minimal) { - assert(to == NMT_summary || to == NMT_detail, "Just check"); - VirtualMemorySummary::reset(); - } else if (to == NMT_minimal) { + assert (from != NMT_minimal, "cannot convert from the lowest tracking level to anything"); + if (to == NMT_minimal) { assert(from == NMT_summary || from == NMT_detail, "Just check"); // Clean up virtual memory tracking data structures. ThreadCritical tc; + // Check for potential race with other thread calling transition if (_reserved_regions != NULL) { delete _reserved_regions; _reserved_regions = NULL;
--- a/src/share/vm/services/virtualMemoryTracker.hpp Fri Oct 31 21:04:37 2014 +0000 +++ b/src/share/vm/services/virtualMemoryTracker.hpp Tue Nov 04 17:16:46 2014 +0000 @@ -62,11 +62,6 @@ _committed -= sz; } - void reset() { - _reserved = 0; - _committed = 0; - } - inline size_t reserved() const { return _reserved; } inline size_t committed() const { return _committed; } }; @@ -123,12 +118,6 @@ return amount; } - inline void reset() { - for (int index = 0; index < mt_number_of_types; index ++) { - _virtual_memory[index].reset(); - } - } - void copy_to(VirtualMemorySnapshot* s) { for (int index = 0; index < mt_number_of_types; index ++) { s->_virtual_memory[index] = _virtual_memory[index]; @@ -174,10 +163,6 @@ as_snapshot()->copy_to(s); } - static inline void reset() { - as_snapshot()->reset(); - } - static VirtualMemorySnapshot* as_snapshot() { return (VirtualMemorySnapshot*)_snapshot; }
--- a/src/share/vm/utilities/vmError.cpp Fri Oct 31 21:04:37 2014 +0000 +++ b/src/share/vm/utilities/vmError.cpp Tue Nov 04 17:16:46 2014 +0000 @@ -774,7 +774,7 @@ STEP(228, "(Native Memory Tracking)" ) if (_verbose) { - MemTracker::final_report(st); + MemTracker::error_report(st); } STEP(230, "" )
--- a/test/Makefile Fri Oct 31 21:04:37 2014 +0000 +++ b/test/Makefile Tue Nov 04 17:16:46 2014 +0000 @@ -1,5 +1,5 @@ # -# Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1995, 2014, 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 @@ -23,14 +23,36 @@ # # -# Makefile to run various jdk tests +# Makefile to run various hotspot tests # GETMIXEDPATH=echo -# Get OS/ARCH specifics -OSNAME = $(shell uname -s) -ifeq ($(OSNAME), SunOS) +# Utilities used +AWK = awk +CAT = cat +CD = cd +CHMOD = chmod +CP = cp +CUT = cut +DIRNAME = dirname +ECHO = echo +EGREP = egrep +EXPAND = expand +FIND = find +MKDIR = mkdir +PWD = pwd +SED = sed +SORT = sort +TEE = tee +UNAME = uname +UNIQ = uniq +WC = wc +ZIP = zip + +# Get OS name from uname (Cygwin inexplicably adds _NT-5.1) +UNAME_S := $(shell $(UNAME) -s | $(CUT) -f1 -d_) +ifeq ($(UNAME_S), SunOS) PLATFORM = solaris SLASH_JAVA = /java ARCH = $(shell uname -p) @@ -38,7 +60,7 @@ ARCH=i586 endif endif -ifeq ($(OSNAME), Linux) +ifeq ($(UNAME_S), Linux) PLATFORM = linux SLASH_JAVA = /java ARCH = $(shell uname -m) @@ -46,7 +68,7 @@ ARCH = i586 endif endif -ifeq ($(OSNAME), Darwin) +ifeq ($(UNAME_S), Darwin) PLATFORM = bsd SLASH_JAVA = /java ARCH = $(shell uname -m) @@ -54,7 +76,7 @@ ARCH = i586 endif endif -ifeq ($(findstring BSD,$(OSNAME)), BSD) +ifeq ($(findstring BSD,$(UNAME_S)), BSD) PLATFORM = bsd SLASH_JAVA = /java ARCH = $(shell uname -m) @@ -63,12 +85,12 @@ endif endif ifeq ($(PLATFORM),) - # detect wether we're running in MKS or cygwin - ifeq ($(OSNAME), Windows_NT) # MKS + # detect whether we're running in MKS or cygwin + ifeq ($(UNAME_S), Windows_NT) # MKS GETMIXEDPATH=dosname -s endif - ifeq ($(findstring CYGWIN,$(OSNAME)), CYGWIN) - GETMIXEDPATH=cygpath -m -s + ifeq ($(findstring CYGWIN,$(UNAME_S)), CYGWIN) + GETMIXEDPATH=cygpath -m endif PLATFORM = windows SLASH_JAVA = J: @@ -92,13 +114,6 @@ SLASH_JAVA = $(ALT_SLASH_JAVA) endif -# Utilities used -CD = cd -CP = cp -ECHO = echo -MKDIR = mkdir -ZIP = zip - # Root of this test area (important to use full paths in some places) TEST_ROOT := $(shell pwd) @@ -136,21 +151,82 @@ endif # How to create the test bundle (pass or fail, we want to create this) -BUNDLE_UP = ( $(MKDIR) -p `dirname $(ARCHIVE_BUNDLE)` \ - && $(CD) $(ABS_TEST_OUTPUT_DIR) \ - && $(ZIP) -q -r $(ARCHIVE_BUNDLE) . ) -BUNDLE_UP_FAILED = ( exitCode=$$? && $(BUNDLE_UP) && exit $${exitCode} ) +# Follow command with ";$(BUNDLE_UP_AND_EXIT)", so it always gets executed. +ZIP_UP_RESULTS = ( $(MKDIR) -p `$(DIRNAME) $(ARCHIVE_BUNDLE)` \ + && $(CD) $(ABS_TEST_OUTPUT_DIR) \ + && $(CHMOD) -R a+r . \ + && $(ZIP) -q -r $(ARCHIVE_BUNDLE) . ) + +# important results files +SUMMARY_TXT = $(shell $(GETMIXEDPATH) "$(ABS_TEST_OUTPUT_DIR)/JTreport/text/summary.txt") +STATS_TXT_NAME = Stats.txt +STATS_TXT = $(shell $(GETMIXEDPATH) "$(ABS_TEST_OUTPUT_DIR)/$(STATS_TXT_NAME)") +RUNLIST = $(shell $(GETMIXEDPATH) "$(ABS_TEST_OUTPUT_DIR)/runlist.txt") +PASSLIST = $(shell $(GETMIXEDPATH) "$(ABS_TEST_OUTPUT_DIR)/passlist.txt") +FAILLIST = $(shell $(GETMIXEDPATH) "$(ABS_TEST_OUTPUT_DIR)/faillist.txt") +EXITCODE = $(shell $(GETMIXEDPATH) "$(ABS_TEST_OUTPUT_DIR)/exitcode.txt") + +TESTEXIT = \ + if [ ! -s $(EXITCODE) ] ; then \ + $(ECHO) "ERROR: EXITCODE file not filled in."; \ + $(ECHO) "1" > $(EXITCODE); \ + fi ; \ + testExitCode=`$(CAT) $(EXITCODE)`; \ + $(ECHO) "EXIT CODE: $${testExitCode}"; \ + exit $${testExitCode} + +BUNDLE_UP_AND_EXIT = \ +( \ + jtregExitCode=$$? && \ + _summary="$(SUMMARY_TXT)"; \ + $(RM) -f $(STATS_TXT) $(RUNLIST) $(PASSLIST) $(FAILLIST) $(EXITCODE); \ + $(ECHO) "$${jtregExitCode}" > $(EXITCODE); \ + if [ -r "$${_summary}" ] ; then \ + $(ECHO) "Summary: $(UNIQUE_DIR)" > $(STATS_TXT); \ + $(EXPAND) $${_summary} | $(EGREP) -v ' Not run\.' > $(RUNLIST); \ + $(EGREP) ' Passed\.' $(RUNLIST) \ + | $(EGREP) -v ' Error\.' \ + | $(EGREP) -v ' Failed\.' > $(PASSLIST); \ + ( $(EGREP) ' Failed\.' $(RUNLIST); \ + $(EGREP) ' Error\.' $(RUNLIST); \ + $(EGREP) -v ' Passed\.' $(RUNLIST) ) \ + | $(SORT) | $(UNIQ) > $(FAILLIST); \ + if [ $${jtregExitCode} != 0 -o -s $(FAILLIST) ] ; then \ + $(EXPAND) $(FAILLIST) \ + | $(CUT) -d' ' -f1 \ + | $(SED) -e 's@^@FAILED: @' >> $(STATS_TXT); \ + if [ $${jtregExitCode} = 0 ] ; then \ + jtregExitCode=1; \ + fi; \ + fi; \ + runc="`$(CAT) $(RUNLIST) | $(WC) -l | $(AWK) '{print $$1;}'`"; \ + passc="`$(CAT) $(PASSLIST) | $(WC) -l | $(AWK) '{print $$1;}'`"; \ + failc="`$(CAT) $(FAILLIST) | $(WC) -l | $(AWK) '{print $$1;}'`"; \ + exclc="FIXME CODETOOLS-7900176"; \ + $(ECHO) "TEST STATS: name=$(UNIQUE_DIR) run=$${runc} pass=$${passc} fail=$${failc}" \ + >> $(STATS_TXT); \ + else \ + $(ECHO) "Missing file: $${_summary}" >> $(STATS_TXT); \ + fi; \ + if [ -f $(STATS_TXT) ] ; then \ + $(CAT) $(STATS_TXT); \ + fi; \ + $(ZIP_UP_RESULTS) ; \ + $(TESTEXIT) \ +) ################################################################ # Default make rule (runs jtreg_tests) -all: jtreg_tests +all: hotspot_all @$(ECHO) "Testing completed successfully" -# Support "hotspot_" prefixed test make targets too -# The hotspot_% targets are for example invoked by the top level Makefile +# Support "hotspot_" prefixed test make targets (too) +# The hotspot_% targets are used by the top level Makefile +# Unless explicitly defined below, hotspot_<x> is interpreted as a jtreg test group name hotspot_%: - $(MAKE) $* + $(ECHO) "Running tests: $@" + $(MAKE) -j 1 TEST_SELECTION=":$@" UNIQUE_DIR=$@ jtreg_tests; # Prep for output prep: clean @@ -168,41 +244,64 @@ # Expect JT_HOME to be set for jtreg tests. (home for jtreg) ifndef JT_HOME - JT_HOME = $(SLASH_JAVA)/re/jtreg/4.0/promoted/latest/binaries/jtreg -endif -ifdef JPRT_JTREG_HOME - JT_HOME = $(JPRT_JTREG_HOME) + JT_HOME = $(SLASH_JAVA)/re/jtreg/4.1/promoted/latest/binaries/jtreg + ifdef JPRT_JTREG_HOME + JT_HOME = $(JPRT_JTREG_HOME) + endif endif -# Expect JPRT to set TESTDIRS to the jtreg test dirs -JTREG_TESTDIRS = demo/jvmti/gctest demo/jvmti/hprof +# When called from JPRT the TESTDIRS variable is set to the jtreg tests to run ifdef TESTDIRS - JTREG_TESTDIRS = $(TESTDIRS) + TEST_SELECTION = $(TESTDIRS) +endif + +ifdef CONCURRENCY + EXTRA_JTREG_OPTIONS += -concurrency:$(CONCURRENCY) endif # Default JTREG to run JTREG = $(JT_HOME)/bin/jtreg +# Only run automatic tests +JTREG_BASIC_OPTIONS += -a +# Report details on all failed or error tests, times too +JTREG_BASIC_OPTIONS += -v:fail,error,time +# Retain all files for failing tests +JTREG_BASIC_OPTIONS += -retain:fail,error +# Ignore tests are not run and completely silent about it +JTREG_IGNORE_OPTION = -ignore:quiet +JTREG_BASIC_OPTIONS += $(JTREG_IGNORE_OPTION) +# Add any extra options +JTREG_BASIC_OPTIONS += $(EXTRA_JTREG_OPTIONS) +# Set other vm and test options +JTREG_TEST_OPTIONS = $(JAVA_ARGS:%=-javaoptions:%) $(JAVA_OPTIONS:%=-vmoption:%) $(JAVA_VM_ARGS:%=-vmoption:%) + # Option to tell jtreg to not run tests marked with "ignore" ifeq ($(PLATFORM), windows) JTREG_KEY_OPTION = -k:!ignore else JTREG_KEY_OPTION = -k:\!ignore endif - -#EXTRA_JTREG_OPTIONS = +JTREG_BASIC_OPTIONS += $(JTREG_KEY_OPTION) + +# Make sure jtreg exists +$(JTREG): $(JT_HOME) -jtreg_tests: prep $(JT_HOME) $(PRODUCT_HOME) $(JTREG) - $(JTREG) -a -v:fail,error \ - $(JTREG_KEY_OPTION) \ - $(EXTRA_JTREG_OPTIONS) \ - -r:$(shell $(GETMIXEDPATH) "$(ABS_TEST_OUTPUT_DIR)")/JTreport \ - -w:$(shell $(GETMIXEDPATH) "$(ABS_TEST_OUTPUT_DIR)")/JTwork \ - -jdk:$(shell $(GETMIXEDPATH) "$(PRODUCT_HOME)") \ - $(JAVA_OPTIONS:%=-vmoption:%) \ - $(JTREG_TESTDIRS) \ - || $(BUNDLE_UP_FAILED) - $(BUNDLE_UP) +jtreg_tests: prep $(PRODUCT_HOME) $(JTREG) + ( \ + ( JT_HOME=$(shell $(GETMIXEDPATH) "$(JT_HOME)"); \ + export JT_HOME; \ + $(shell $(GETMIXEDPATH) "$(JTREG)") \ + $(JTREG_BASIC_OPTIONS) \ + -r:$(shell $(GETMIXEDPATH) "$(ABS_TEST_OUTPUT_DIR)/JTreport") \ + -w:$(shell $(GETMIXEDPATH) "$(ABS_TEST_OUTPUT_DIR)/JTwork") \ + -jdk:$(shell $(GETMIXEDPATH) "$(PRODUCT_HOME)") \ + $(JTREG_EXCLUSIONS) \ + $(JTREG_TEST_OPTIONS) \ + $(TEST_SELECTION) \ + ) ; \ + $(BUNDLE_UP_AND_EXIT) \ + ) 2>&1 | $(TEE) $(ABS_TEST_OUTPUT_DIR)/output.txt ; $(TESTEXIT) PHONY_LIST += jtreg_tests @@ -210,7 +309,7 @@ # clienttest (make sure various basic java client options work) -clienttest: prep $(PRODUCT_HOME) +hotspot_clienttest clienttest: prep $(PRODUCT_HOME) $(PRODUCT_HOME)/bin/java $(JAVA_OPTIONS) -version $(PRODUCT_HOME)/bin/java $(JAVA_OPTIONS) -help $(PRODUCT_HOME)/bin/java $(JAVA_OPTIONS) -X @@ -218,73 +317,38 @@ $(RM) $(PRODUCT_HOME)/jre/bin/client/classes.jsa $(PRODUCT_HOME)/bin/java $(JAVA_OPTIONS) -Xshare:dump -PHONY_LIST += clienttest +PHONY_LIST += hotspot_clienttest clienttest + +################################################################ + +# minimaltest (make sure various basic java minimal options work) + +hotspot_minimaltest minimaltest: prep $(PRODUCT_HOME) + $(PRODUCT_HOME)/bin/java $(JAVA_OPTIONS) -version + $(PRODUCT_HOME)/bin/java $(JAVA_OPTIONS) -help + $(PRODUCT_HOME)/bin/java $(JAVA_OPTIONS) -X + +PHONY_LIST += hotspot_minimaltest minimaltest ################################################################ # servertest (make sure various basic java server options work) -servertest: prep $(PRODUCT_HOME) +hotspot_servertest servertest: prep $(PRODUCT_HOME) $(PRODUCT_HOME)/bin/java $(JAVA_OPTIONS) -version $(PRODUCT_HOME)/bin/java $(JAVA_OPTIONS) -help $(PRODUCT_HOME)/bin/java $(JAVA_OPTIONS) -X -PHONY_LIST += servertest +PHONY_LIST += hotspot_servertest servertest ################################################################ # internalvmtests (run internal unit tests inside the VM) -internalvmtests: prep $(PRODUCT_HOME) +hotspot_internalvmtests internalvmtests: prep $(PRODUCT_HOME) $(PRODUCT_HOME)/bin/java $(JAVA_OPTIONS) -XX:+ExecuteInternalVMTests -version -PHONY_LIST += internalvmtests - -################################################################ - -# wbapitest (make sure the whitebox testing api classes work - -wbapitest: prep $(JT_HOME) $(PRODUCT_HOME) $(JTREG) - $(JTREG) -a -v:fail,error \ - $(JTREG_KEY_OPTION) \ - $(EXTRA_JTREG_OPTIONS) \ - -r:$(shell $(GETMIXEDPATH) "$(ABS_TEST_OUTPUT_DIR)")/JTreport \ - -w:$(shell $(GETMIXEDPATH) "$(ABS_TEST_OUTPUT_DIR)")/JTwork \ - -jdk:$(shell $(GETMIXEDPATH) "$(PRODUCT_HOME)") \ - $(JAVA_OPTIONS:%=-vmoption:%) \ - $(shell $(GETMIXEDPATH) "$(TEST_ROOT)")/sanity \ - || $(BUNDLE_UP_FAILED) - $(BUNDLE_UP) - -PHONY_LIST += wbapitest - -################################################################ - -# packtest - -# Expect JPRT to set JPRT_PACKTEST_HOME. -PACKTEST_HOME = /net/jprt-web.sfbay.sun.com/jprt/allproducts/packtest -ifdef JPRT_PACKTEST_HOME - PACKTEST_HOME = $(JPRT_PACKTEST_HOME) -endif - -#EXTRA_PACKTEST_OPTIONS = - -packtest: prep $(PACKTEST_HOME)/ptest $(PRODUCT_HOME) - ( $(CD) $(PACKTEST_HOME) && \ - $(PACKTEST_HOME)/ptest \ - -t "$(PRODUCT_HOME)" \ - $(PACKTEST_STRESS_OPTION) \ - $(EXTRA_PACKTEST_OPTIONS) \ - -W $(ABS_TEST_OUTPUT_DIR) \ - $(JAVA_OPTIONS:%=-J %) \ - ) || $(BUNDLE_UP_FAILED) - $(BUNDLE_UP) - -packtest_stress: PACKTEST_STRESS_OPTION=-s -packtest_stress: packtest - -PHONY_LIST += packtest packtest_stress +PHONY_LIST += hotspot_internalvmtests internalvmtests ################################################################ @@ -292,4 +356,3 @@ .PHONY: all clean prep $(PHONY_LIST) ################################################################ -
--- a/test/TEST.groups Fri Oct 31 21:04:37 2014 +0000 +++ b/test/TEST.groups Tue Nov 04 17:16:46 2014 +0000 @@ -125,6 +125,27 @@ -:needs_jdk +# When called from top level the test suites use the hotspot_ prefix +hotspot_wbapitest = \ + sanity/ + +hotspot_compiler = \ + sanity/ExecuteInternalVMTests.java + +hotspot_gc = \ + sanity/ExecuteInternalVMTests.java + +hotspot_runtime = \ + sanity/ExecuteInternalVMTests.java + +hotspot_serviceability = \ + sanity/ExecuteInternalVMTests.java + +hotspot_all = \ + :hotspot_compiler \ + :hotspot_gc \ + :hotspot_runtime \ + :hotspot_serviceability # Tests that require compact3 API's # needs_compact3 = \ @@ -144,6 +165,13 @@ gc/metaspace/TestMetaspaceMemoryPool.java \ gc/arguments/TestDynMinHeapFreeRatio.java \ gc/arguments/TestDynMaxHeapFreeRatio.java \ + gc/g1/TestShrinkAuxiliaryData00.java \ + gc/g1/TestShrinkAuxiliaryData05.java \ + gc/g1/TestShrinkAuxiliaryData10.java \ + gc/g1/TestShrinkAuxiliaryData15.java \ + gc/g1/TestShrinkAuxiliaryData20.java \ + gc/g1/TestShrinkAuxiliaryData25.java \ + gc/g1/TestShrinkAuxiliaryData30.java \ runtime/InternalApi/ThreadCpuTimesDeadlock.java \ serviceability/threads/TestFalseDeadLock.java \ serviceability/jvmti/GetObjectSizeOverflow.java \
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/exceptions/CatchInlineExceptions.java Tue Nov 04 17:16:46 2014 +0000 @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2014, 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 + * @bug 8059299 + * @summary assert(adr_type != NULL) failed: expecting TypeKlassPtr + * @run main/othervm -Xbatch CatchInlineExceptions + */ + +class Exception1 extends Exception {}; +class Exception2 extends Exception {}; + +public class CatchInlineExceptions { + private static int counter0; + private static int counter1; + private static int counter2; + private static int counter; + + static void foo(int i) throws Exception { + if ((i & 1023) == 2) { + counter0++; + throw new Exception2(); + } + } + + static void test(int i) throws Exception { + try { + foo(i); + } + catch (Exception e) { + if (e instanceof Exception1) { + counter1++; + } else if (e instanceof Exception2) { + counter2++; + } + counter++; + throw e; + } + } + + public static void main(String[] args) throws Throwable { + for (int i = 0; i < 15000; i++) { + try { + test(i); + } catch (Exception e) { + // expected + } + } + if (counter1 != 0) { + throw new RuntimeException("Failed: counter1(" + counter1 + ") != 0"); + } + if (counter2 != counter0) { + throw new RuntimeException("Failed: counter2(" + counter2 + ") != counter0(" + counter0 + ")"); + } + if (counter2 != counter) { + throw new RuntimeException("Failed: counter2(" + counter2 + ") != counter(" + counter + ")"); + } + System.out.println("TEST PASSED"); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/osr/TestRangeCheck.java Tue Nov 04 17:16:46 2014 +0000 @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2014, 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 TestRangeCheck + * @bug 8054883 + * @summary Tests that range check is not skipped + */ + +public class TestRangeCheck { + public static void main(String args[]) { + try { + test(); + throw new AssertionError("Expected ArrayIndexOutOfBoundsException was not thrown"); + } catch (ArrayIndexOutOfBoundsException e) { + System.out.println("Expected ArrayIndexOutOfBoundsException was thrown"); + } + } + + private static void test() { + int arr[] = new int[1]; + int result = 1; + + // provoke OSR compilation + for (int i = 0; i < Integer.MAX_VALUE; i++) { + } + + if (result > 0 && arr[~result] > 0) { + arr[~result] = 0; + } + } +}
--- a/test/gc/class_unloading/AllocateBeyondMetaspaceSize.java Fri Oct 31 21:04:37 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,59 +0,0 @@ -/* - * Copyright (c) 2014, 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.hotspot.WhiteBox; - -class AllocateBeyondMetaspaceSize { - public static Object dummy; - - public static void main(String [] args) { - if (args.length != 2) { - throw new IllegalArgumentException("Usage: <MetaspaceSize> <YoungGenSize>"); - } - - long metaspaceSize = Long.parseLong(args[0]); - long youngGenSize = Long.parseLong(args[1]); - - run(metaspaceSize, youngGenSize); - } - - private static void run(long metaspaceSize, long youngGenSize) { - WhiteBox wb = WhiteBox.getWhiteBox(); - - long allocationBeyondMetaspaceSize = metaspaceSize * 2; - long metaspace = wb.allocateMetaspace(null, allocationBeyondMetaspaceSize); - - triggerYoungGC(youngGenSize); - - wb.freeMetaspace(null, metaspace, metaspace); - } - - private static void triggerYoungGC(long youngGenSize) { - long approxAllocSize = 32 * 1024; - long numAllocations = 2 * youngGenSize / approxAllocSize; - - for (long i = 0; i < numAllocations; i++) { - dummy = new byte[(int)approxAllocSize]; - } - } -}
--- a/test/gc/class_unloading/TestCMSClassUnloadingEnabledHWM.java Fri Oct 31 21:04:37 2014 +0000 +++ b/test/gc/class_unloading/TestCMSClassUnloadingEnabledHWM.java Tue Nov 04 17:16:46 2014 +0000 @@ -26,7 +26,7 @@ * @key gc * @bug 8049831 * @library /testlibrary /testlibrary/whitebox - * @build TestCMSClassUnloadingEnabledHWM AllocateBeyondMetaspaceSize + * @build TestCMSClassUnloadingEnabledHWM * @run main ClassFileInstaller sun.hotspot.WhiteBox * @run driver TestCMSClassUnloadingEnabledHWM * @summary Test that -XX:-CMSClassUnloadingEnabled will trigger a Full GC when more than MetaspaceSize metadata is allocated. @@ -34,9 +34,11 @@ import com.oracle.java.testlibrary.OutputAnalyzer; import com.oracle.java.testlibrary.ProcessTools; - +import java.lang.management.GarbageCollectorMXBean; +import java.lang.management.ManagementFactory; import java.util.ArrayList; import java.util.Arrays; +import sun.hotspot.WhiteBox; public class TestCMSClassUnloadingEnabledHWM { private static long MetaspaceSize = 32 * 1024 * 1024; @@ -47,15 +49,18 @@ "-Xbootclasspath/a:.", "-XX:+UnlockDiagnosticVMOptions", "-XX:+WhiteBoxAPI", + "-Xmx128m", + "-XX:CMSMaxAbortablePrecleanTime=1", + "-XX:CMSWaitDuration=50", "-XX:MetaspaceSize=" + MetaspaceSize, "-Xmn" + YoungGenSize, "-XX:+UseConcMarkSweepGC", "-XX:" + (enableUnloading ? "+" : "-") + "CMSClassUnloadingEnabled", "-XX:+PrintHeapAtGC", "-XX:+PrintGCDetails", - "AllocateBeyondMetaspaceSize", - "" + MetaspaceSize, - "" + YoungGenSize); + "-XX:+PrintGCTimeStamps", + TestCMSClassUnloadingEnabledHWM.AllocateBeyondMetaspaceSize.class.getName(), + "" + MetaspaceSize); return new OutputAnalyzer(pb.start()); } @@ -87,5 +92,37 @@ testWithCMSClassUnloading(); testWithoutCMSClassUnloading(); } + + public static class AllocateBeyondMetaspaceSize { + public static void main(String [] args) throws Exception { + if (args.length != 1) { + throw new IllegalArgumentException("Usage: <MetaspaceSize>"); + } + + WhiteBox wb = WhiteBox.getWhiteBox(); + + // Allocate past the MetaspaceSize limit. + long metaspaceSize = Long.parseLong(args[0]); + long allocationBeyondMetaspaceSize = metaspaceSize * 2; + long metaspace = wb.allocateMetaspace(null, allocationBeyondMetaspaceSize); + + // Wait for at least one GC to occur. The caller will parse the log files produced. + GarbageCollectorMXBean cmsGCBean = getCMSGCBean(); + while (cmsGCBean.getCollectionCount() == 0) { + Thread.sleep(100); + } + + wb.freeMetaspace(null, metaspace, metaspace); + } + + private static GarbageCollectorMXBean getCMSGCBean() { + for (GarbageCollectorMXBean gcBean : ManagementFactory.getGarbageCollectorMXBeans()) { + if (gcBean.getObjectName().toString().equals("java.lang:type=GarbageCollector,name=ConcurrentMarkSweep")) { + return gcBean; + } + } + return null; + } + } }
--- a/test/gc/class_unloading/TestG1ClassUnloadingHWM.java Fri Oct 31 21:04:37 2014 +0000 +++ b/test/gc/class_unloading/TestG1ClassUnloadingHWM.java Tue Nov 04 17:16:46 2014 +0000 @@ -26,7 +26,7 @@ * @key gc * @bug 8049831 * @library /testlibrary /testlibrary/whitebox - * @build TestG1ClassUnloadingHWM AllocateBeyondMetaspaceSize + * @build TestG1ClassUnloadingHWM * @run main ClassFileInstaller sun.hotspot.WhiteBox * @run driver TestG1ClassUnloadingHWM * @summary Test that -XX:-ClassUnloadingWithConcurrentMark will trigger a Full GC when more than MetaspaceSize metadata is allocated. @@ -34,9 +34,9 @@ import com.oracle.java.testlibrary.OutputAnalyzer; import com.oracle.java.testlibrary.ProcessTools; - import java.util.ArrayList; import java.util.Arrays; +import sun.hotspot.WhiteBox; public class TestG1ClassUnloadingHWM { private static long MetaspaceSize = 32 * 1024 * 1024; @@ -53,7 +53,7 @@ "-XX:" + (enableUnloading ? "+" : "-") + "ClassUnloadingWithConcurrentMark", "-XX:+PrintHeapAtGC", "-XX:+PrintGCDetails", - "AllocateBeyondMetaspaceSize", + TestG1ClassUnloadingHWM.AllocateBeyondMetaspaceSize.class.getName(), "" + MetaspaceSize, "" + YoungGenSize); return new OutputAnalyzer(pb.start()); @@ -87,5 +87,36 @@ testWithG1ClassUnloading(); testWithoutG1ClassUnloading(); } + + public static class AllocateBeyondMetaspaceSize { + public static Object dummy; + + public static void main(String [] args) throws Exception { + if (args.length != 2) { + throw new IllegalArgumentException("Usage: <MetaspaceSize> <YoungGenSize>"); + } + + WhiteBox wb = WhiteBox.getWhiteBox(); + + // Allocate past the MetaspaceSize limit + long metaspaceSize = Long.parseLong(args[0]); + long allocationBeyondMetaspaceSize = metaspaceSize * 2; + long metaspace = wb.allocateMetaspace(null, allocationBeyondMetaspaceSize); + + long youngGenSize = Long.parseLong(args[1]); + triggerYoungGCs(youngGenSize); + + wb.freeMetaspace(null, metaspace, metaspace); + } + + public static void triggerYoungGCs(long youngGenSize) { + long approxAllocSize = 32 * 1024; + long numAllocations = 2 * youngGenSize / approxAllocSize; + + for (long i = 0; i < numAllocations; i++) { + dummy = new byte[(int)approxAllocSize]; + } + } + } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/gc/g1/TestShrinkAuxiliaryData.java Tue Nov 04 17:16:46 2014 +0000 @@ -0,0 +1,286 @@ +/* + * Copyright (c) 2014, 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 static com.oracle.java.testlibrary.Asserts.assertLessThanOrEqual; +import com.oracle.java.testlibrary.OutputAnalyzer; +import com.oracle.java.testlibrary.Platform; +import com.oracle.java.testlibrary.ProcessTools; +import com.oracle.java.testlibrary.Utils; +import java.io.IOException; +import java.lang.management.ManagementFactory; +import java.lang.management.MemoryUsage; +import java.text.DecimalFormat; +import java.text.DecimalFormatSymbols; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; +import sun.misc.Unsafe; + +public class TestShrinkAuxiliaryData { + + private final static String[] initialOpts = new String[]{ + "-XX:MinHeapFreeRatio=10", + "-XX:MaxHeapFreeRatio=11", + "-XX:+UseG1GC", + "-XX:G1HeapRegionSize=1m", + "-XX:+PrintGCDetails" + }; + + private final int RSetCacheSize; + + protected TestShrinkAuxiliaryData(int RSetCacheSize) { + this.RSetCacheSize = RSetCacheSize; + } + + protected void test() throws Exception { + ArrayList<String> vmOpts = new ArrayList(); + Collections.addAll(vmOpts, initialOpts); + + int maxCacheSize = Math.max(0, Math.min(31, getMaxCacheSize())); + if (maxCacheSize < RSetCacheSize) { + System.out.format("Skiping test for %d cache size due max cache size %d", + RSetCacheSize, maxCacheSize + ); + return; + } + + printTestInfo(maxCacheSize); + + vmOpts.add("-XX:G1ConcRSLogCacheSize=" + RSetCacheSize); + + vmOpts.addAll(Arrays.asList(Utils.getFilteredTestJavaOpts( + ShrinkAuxiliaryDataTest.prohibitedVmOptions))); + + // for 32 bits ObjectAlignmentInBytes is not a option + if (Platform.is32bit()) { + ArrayList<String> vmOptsWithoutAlign = new ArrayList(vmOpts); + vmOptsWithoutAlign.add(ShrinkAuxiliaryDataTest.class.getName()); + performTest(vmOptsWithoutAlign); + return; + } + + for (int alignment = 3; alignment <= 8; alignment++) { + ArrayList<String> vmOptsWithAlign = new ArrayList(vmOpts); + vmOptsWithAlign.add("-XX:ObjectAlignmentInBytes=" + + (int) Math.pow(2, alignment)); + vmOptsWithAlign.add(ShrinkAuxiliaryDataTest.class.getName()); + + performTest(vmOptsWithAlign); + } + } + + private void performTest(List<String> opts) throws Exception { + ProcessBuilder pb + = ProcessTools.createJavaProcessBuilder( + opts.toArray(new String[opts.size()]) + ); + + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldHaveExitValue(0); + } + + private void printTestInfo(int maxCacheSize) { + + DecimalFormat grouped = new DecimalFormat("000,000"); + DecimalFormatSymbols formatSymbols = grouped.getDecimalFormatSymbols(); + formatSymbols.setGroupingSeparator(' '); + grouped.setDecimalFormatSymbols(formatSymbols); + + System.out.format("Test will use %s bytes of memory of %s available%n" + + "Available memory is %s with %d bytes pointer size - can save %s pointers%n" + + "Max cache size: 2^%d = %s elements%n", + grouped.format(ShrinkAuxiliaryDataTest.getMemoryUsedByTest()), + grouped.format(Runtime.getRuntime().freeMemory()), + grouped.format(Runtime.getRuntime().freeMemory() + - ShrinkAuxiliaryDataTest.getMemoryUsedByTest()), + Unsafe.ADDRESS_SIZE, + grouped.format((Runtime.getRuntime().freeMemory() + - ShrinkAuxiliaryDataTest.getMemoryUsedByTest()) + / Unsafe.ADDRESS_SIZE), + maxCacheSize, + grouped.format((int) Math.pow(2, maxCacheSize)) + ); + } + + /** + * Detects maximum possible size of G1ConcRSLogCacheSize available for + * current process based on maximum available process memory size + * + * @return power of two + */ + private static int getMaxCacheSize() { + long availableMemory = Runtime.getRuntime().freeMemory() + - ShrinkAuxiliaryDataTest.getMemoryUsedByTest() - 1l; + if (availableMemory <= 0) { + return 0; + } + long availablePointersCount = availableMemory / Unsafe.ADDRESS_SIZE; + return (63 - (int) Long.numberOfLeadingZeros(availablePointersCount)); + } + + static class ShrinkAuxiliaryDataTest { + + public static void main(String[] args) throws IOException { + int iterateCount = DEFAULT_ITERATION_COUNT; + + if (args.length > 0) { + try { + iterateCount = Integer.parseInt(args[0]); + } catch (NumberFormatException e) { + //num_iterate remains default + } + } + + new ShrinkAuxiliaryDataTest().test(iterateCount); + } + + class GarbageObject { + + private final List<byte[]> payload = new ArrayList(); + private final List<GarbageObject> ref = new LinkedList(); + + public GarbageObject(int size) { + payload.add(new byte[size]); + } + + public void addRef(GarbageObject g) { + ref.add(g); + } + + public void mutate() { + if (!payload.isEmpty() && payload.get(0).length > 0) { + payload.get(0)[0] = (byte) (Math.random() * Byte.MAX_VALUE); + } + } + } + + private final List<GarbageObject> garbage = new ArrayList(); + + public void test(int num_iterate) throws IOException { + + allocate(); + link(); + mutate(); + deallocate(); + + MemoryUsage muBeforeHeap + = ManagementFactory.getMemoryMXBean().getHeapMemoryUsage(); + MemoryUsage muBeforeNonHeap + = ManagementFactory.getMemoryMXBean().getNonHeapMemoryUsage(); + + for (int i = 0; i < num_iterate; i++) { + allocate(); + link(); + mutate(); + deallocate(); + } + + System.gc(); + MemoryUsage muAfterHeap + = ManagementFactory.getMemoryMXBean().getHeapMemoryUsage(); + MemoryUsage muAfterNonHeap + = ManagementFactory.getMemoryMXBean().getNonHeapMemoryUsage(); + + assertLessThanOrEqual(muAfterHeap.getCommitted(), muBeforeHeap.getCommitted(), + String.format("heap decommit failed - after > before: %d > %d", + muAfterHeap.getCommitted(), muBeforeHeap.getCommitted() + ) + ); + + if (muAfterHeap.getCommitted() < muBeforeHeap.getCommitted()) { + assertLessThanOrEqual(muAfterNonHeap.getCommitted(), muBeforeNonHeap.getCommitted(), + String.format("non-heap decommit failed - after > before: %d > %d", + muAfterNonHeap.getCommitted(), muBeforeNonHeap.getCommitted() + ) + ); + } + } + + private void allocate() { + for (int r = 0; r < REGIONS_TO_ALLOCATE; r++) { + for (int i = 0; i < NUM_OBJECTS_PER_REGION; i++) { + GarbageObject g = new GarbageObject(REGION_SIZE + / NUM_OBJECTS_PER_REGION); + garbage.add(g); + } + } + } + + /** + * Iterate through all allocated objects, and link to objects in another + * regions + */ + private void link() { + for (int ig = 0; ig < garbage.size(); ig++) { + int regionNumber = ig / NUM_OBJECTS_PER_REGION; + + for (int i = 0; i < NUM_LINKS; i++) { + int regionToLink; + do { + regionToLink = (int) (Math.random() + * REGIONS_TO_ALLOCATE); + } while (regionToLink == regionNumber); + + // get random garbage object from random region + garbage.get(ig).addRef(garbage.get(regionToLink + * NUM_OBJECTS_PER_REGION + (int) (Math.random() + * NUM_OBJECTS_PER_REGION))); + } + } + } + + private void mutate() { + for (int ig = 0; ig < garbage.size(); ig++) { + garbage.get(ig).mutate(); + } + } + + private void deallocate() { + garbage.clear(); + System.gc(); + } + + static long getMemoryUsedByTest() { + return REGIONS_TO_ALLOCATE * REGION_SIZE; + } + + private static final int REGION_SIZE = 1024 * 1024; + private static final int DEFAULT_ITERATION_COUNT = 1; // iterate main scenario + private static final int REGIONS_TO_ALLOCATE = 5; + private static final int NUM_OBJECTS_PER_REGION = 10; + private static final int NUM_LINKS = 20; // how many links create for each object + + private static final String[] prohibitedVmOptions = { + // remove this when @requires option will be on duty + "-XX:\\+UseParallelGC", + "-XX:\\+UseSerialGC", + "-XX:\\+UseConcMarkSweepGC", + "-XX:\\+UseParallelOldGC", + "-XX:\\+UseParNewGC", + "-Xconcgc", + "-Xincgc" + }; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/gc/g1/TestShrinkAuxiliaryData00.java Tue Nov 04 17:16:46 2014 +0000 @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2014, 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 TestShrinkAuxiliaryData00 + * @bug 8038423 + * @summary Checks that decommitment occurs for JVM with different + * G1ConcRSLogCacheSize and ObjectAlignmentInBytes options values + * @library /testlibrary /testlibrary/whitebox + * @build TestShrinkAuxiliaryData TestShrinkAuxiliaryData00 + * @run driver/timeout=720 TestShrinkAuxiliaryData00 + */ +public class TestShrinkAuxiliaryData00 { + + public static void main(String[] args) throws Exception { + new TestShrinkAuxiliaryData(0).test(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/gc/g1/TestShrinkAuxiliaryData05.java Tue Nov 04 17:16:46 2014 +0000 @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2014, 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 TestShrinkAuxiliaryData05 + * @bug 8038423 + * @summary Checks that decommitment occurs for JVM with different + * G1ConcRSLogCacheSize and ObjectAlignmentInBytes options values + * @library /testlibrary /testlibrary/whitebox + * @build TestShrinkAuxiliaryData TestShrinkAuxiliaryData05 + * @run driver/timeout=720 TestShrinkAuxiliaryData05 + */ +public class TestShrinkAuxiliaryData05 { + + public static void main(String[] args) throws Exception { + new TestShrinkAuxiliaryData(5).test(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/gc/g1/TestShrinkAuxiliaryData10.java Tue Nov 04 17:16:46 2014 +0000 @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2014, 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 TestShrinkAuxiliaryData10 + * @bug 8038423 + * @summary Checks that decommitment occurs for JVM with different + * G1ConcRSLogCacheSize and ObjectAlignmentInBytes options values + * @library /testlibrary /testlibrary/whitebox + * @build TestShrinkAuxiliaryData TestShrinkAuxiliaryData10 + * @run driver/timeout=720 TestShrinkAuxiliaryData10 + */ +public class TestShrinkAuxiliaryData10 { + + public static void main(String[] args) throws Exception { + new TestShrinkAuxiliaryData(10).test(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/gc/g1/TestShrinkAuxiliaryData15.java Tue Nov 04 17:16:46 2014 +0000 @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2014, 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 TestShrinkAuxiliaryData15 + * @bug 8038423 + * @summary Checks that decommitment occurs for JVM with different + * G1ConcRSLogCacheSize and ObjectAlignmentInBytes options values + * @library /testlibrary /testlibrary/whitebox + * @build TestShrinkAuxiliaryData TestShrinkAuxiliaryData15 + * @run driver/timeout=720 TestShrinkAuxiliaryData15 + */ +public class TestShrinkAuxiliaryData15 { + + public static void main(String[] args) throws Exception { + new TestShrinkAuxiliaryData(15).test(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/gc/g1/TestShrinkAuxiliaryData20.java Tue Nov 04 17:16:46 2014 +0000 @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2014, 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 TestShrinkAuxiliaryData20 + * @bug 8038423 + * @summary Checks that decommitment occurs for JVM with different + * G1ConcRSLogCacheSize and ObjectAlignmentInBytes options values + * @library /testlibrary /testlibrary/whitebox + * @build TestShrinkAuxiliaryData TestShrinkAuxiliaryData20 + * @run driver/timeout=720 TestShrinkAuxiliaryData20 + */ +public class TestShrinkAuxiliaryData20 { + + public static void main(String[] args) throws Exception { + new TestShrinkAuxiliaryData(20).test(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/gc/g1/TestShrinkAuxiliaryData25.java Tue Nov 04 17:16:46 2014 +0000 @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2014, 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 TestShrinkAuxiliaryData25 + * @bug 8038423 + * @summary Checks that decommitment occurs for JVM with different + * G1ConcRSLogCacheSize and ObjectAlignmentInBytes options values + * @library /testlibrary /testlibrary/whitebox + * @build TestShrinkAuxiliaryData TestShrinkAuxiliaryData25 + * @run driver/timeout=720 TestShrinkAuxiliaryData25 + */ +public class TestShrinkAuxiliaryData25 { + + public static void main(String[] args) throws Exception { + new TestShrinkAuxiliaryData(25).test(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/gc/g1/TestShrinkAuxiliaryData30.java Tue Nov 04 17:16:46 2014 +0000 @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2014, 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 TestShrinkAuxiliaryData30 + * @bug 8038423 + * @summary Checks that decommitment occurs for JVM with different + * G1ConcRSLogCacheSize and ObjectAlignmentInBytes options values + * @library /testlibrary /testlibrary/whitebox + * @build TestShrinkAuxiliaryData TestShrinkAuxiliaryData30 + * @run driver/timeout=720 TestShrinkAuxiliaryData30 + */ +public class TestShrinkAuxiliaryData30 { + + public static void main(String[] args) throws Exception { + new TestShrinkAuxiliaryData(30).test(); + } +}
--- a/test/gc/g1/TestSummarizeRSetStatsThreads.java Fri Oct 31 21:04:37 2014 +0000 +++ b/test/gc/g1/TestSummarizeRSetStatsThreads.java Tue Nov 04 17:16:46 2014 +0000 @@ -53,8 +53,8 @@ // a zero in refinement thread numbers indicates that the value in ParallelGCThreads should be used. // Additionally use at least one thread. - int expectedNumRefinementThreads = refinementThreads == 0 ? workerThreads : refinementThreads; - expectedNumRefinementThreads = Math.max(1, expectedNumRefinementThreads); + int expectedNumRefinementThreads = refinementThreads; + // create the pattern made up of n copies of a floating point number pattern String numberPattern = String.format("%0" + expectedNumRefinementThreads + "d", 0) .replace("0", "\\s+\\d+\\.\\d+"); @@ -73,9 +73,9 @@ return; } // different valid combinations of number of refinement and gc worker threads - runTest(0, 0); - runTest(0, 5); - runTest(5, 0); + runTest(1, 1); + runTest(1, 5); + runTest(5, 1); runTest(10, 10); runTest(1, 2); runTest(4, 3);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/gc/metaspace/TestCapacityUntilGCWrapAround.java Tue Nov 04 17:16:46 2014 +0000 @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2014, 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 + * @key gc + * @bug 8049831 + * @library /testlibrary /testlibrary/whitebox + * @build TestCapacityUntilGCWrapAround + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI TestCapacityUntilGCWrapAround + */ + +import sun.hotspot.WhiteBox; + +import com.oracle.java.testlibrary.Asserts; +import com.oracle.java.testlibrary.Platform; + +public class TestCapacityUntilGCWrapAround { + private static long MB = 1024 * 1024; + private static long GB = 1024 * MB; + private static long MAX_UINT = 4 * GB - 1; // On 32-bit platforms + + public static void main(String[] args) { + if (Platform.is32bit()) { + WhiteBox wb = WhiteBox.getWhiteBox(); + + long before = wb.metaspaceCapacityUntilGC(); + // Now force possible overflow of capacity_until_GC. + long after = wb.incMetaspaceCapacityUntilGC(MAX_UINT); + + Asserts.assertGTE(after, before, + "Increasing with MAX_UINT should not cause wrap around: " + after + " < " + before); + Asserts.assertLTE(after, MAX_UINT, + "Increasing with MAX_UINT should not cause value larger than MAX_UINT:" + after); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/runtime/NMT/ChangeTrackingLevel.java Tue Nov 04 17:16:46 2014 +0000 @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2013, 2014, 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 + * @bug 8059100 + * @summary Test that you can decrease NMT tracking level but not increase it. + * @key nmt + * @library /testlibrary /testlibrary/whitebox + * @build ChangeTrackingLevel + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:NativeMemoryTracking=detail ChangeTrackingLevel + */ + +import com.oracle.java.testlibrary.*; +import sun.hotspot.WhiteBox; + +public class ChangeTrackingLevel { + + public static WhiteBox wb = WhiteBox.getWhiteBox(); + public static void main(String args[]) throws Exception { + boolean testChangeLevel = wb.NMTChangeTrackingLevel(); + if (testChangeLevel) { + System.out.println("NMT level change test passed."); + } else { + // it also fails if the VM asserts. + throw new RuntimeException("NMT level change test failed"); + } + } +};
--- a/test/testlibrary/whitebox/sun/hotspot/WhiteBox.java Fri Oct 31 21:04:37 2014 +0000 +++ b/test/testlibrary/whitebox/sun/hotspot/WhiteBox.java Tue Nov 04 17:16:46 2014 +0000 @@ -101,6 +101,7 @@ public native void NMTOverflowHashBucket(long num); public native long NMTMallocWithPseudoStack(long size, int index); public native boolean NMTIsDetailSupported(); + public native boolean NMTChangeTrackingLevel(); // Compiler public native void deoptimizeAll(); @@ -152,6 +153,8 @@ public native void readReservedMemory(); public native long allocateMetaspace(ClassLoader classLoader, long size); public native void freeMetaspace(ClassLoader classLoader, long addr, long size); + public native long incMetaspaceCapacityUntilGC(long increment); + public native long metaspaceCapacityUntilGC(); // force Young GC public native void youngGC();