diff --git a/.hgtags b/.hgtags index aaf78d35e9c..7a1ef94c809 100644 --- a/.hgtags +++ b/.hgtags @@ -285,3 +285,5 @@ b409bc51bc23cfd51f2bd04ea919ec83535af9d0 jdk9-b37 82f4cb44b2d7af2352f48568a64b7b6a5ae960cd jdk9-b40 9fffb959eb4197ff806e4ac12244761815b4deee jdk9-b41 3107be2ba9c6e208a0b86bc7100a141abbc5b5fb jdk9-b42 +6494b13f88a867026ee316b444d9a4fa589dd6bd jdk9-b43 +abbfccd659b91a7bb815d5e36fed635dcdd40f31 jdk9-b44 diff --git a/.hgtags-top-repo b/.hgtags-top-repo index 9cbf0f90d4e..1c8881b0d18 100644 --- a/.hgtags-top-repo +++ b/.hgtags-top-repo @@ -285,3 +285,5 @@ d42c0a90afc3c66ca87543076ec9aafd4b4680de jdk9-b38 cf136458ee747e151a27aa9ea0c1492ea55ef3e7 jdk9-b40 67395f7ca2db3b52e3a62a84888487de5cb9210a jdk9-b41 f7c11da0b0481d49cc7a65a453336c108191e821 jdk9-b42 +02ee8c65622e8bd97496d584e22fc7dcf0edc4ae jdk9-b43 +8994f5d87b3bb5e8d317d4e8ccb326da1a73684a jdk9-b44 diff --git a/common/autoconf/generated-configure.sh b/common/autoconf/generated-configure.sh index 0b1567ce0ce..59c1a8ae9e8 100644 --- a/common/autoconf/generated-configure.sh +++ b/common/autoconf/generated-configure.sh @@ -4329,7 +4329,7 @@ TOOLCHAIN_DESCRIPTION_xlc="IBM XL C/C++" #CUSTOM_AUTOCONF_INCLUDE # Do not change or remove the following line, it is needed for consistency checks: -DATE_WHEN_GENERATED=1418036274 +DATE_WHEN_GENERATED=1418395009 ############################################################################### # @@ -13965,7 +13965,8 @@ $as_echo "$COMPILE_TYPE" >&6; } # ZERO_ARCHDEF is used to enable architecture-specific code case "${OPENJDK_TARGET_CPU}" in - ppc*) ZERO_ARCHDEF=PPC ;; + ppc) ZERO_ARCHDEF=PPC32 ;; + ppc64) ZERO_ARCHDEF=PPC64 ;; s390*) ZERO_ARCHDEF=S390 ;; sparc*) ZERO_ARCHDEF=SPARC ;; x86_64*) ZERO_ARCHDEF=AMD64 ;; diff --git a/common/autoconf/platform.m4 b/common/autoconf/platform.m4 index 27db8d047eb..6f26b855e95 100644 --- a/common/autoconf/platform.m4 +++ b/common/autoconf/platform.m4 @@ -367,7 +367,8 @@ AC_DEFUN([PLATFORM_SETUP_LEGACY_VARS], # ZERO_ARCHDEF is used to enable architecture-specific code case "${OPENJDK_TARGET_CPU}" in - ppc*) ZERO_ARCHDEF=PPC ;; + ppc) ZERO_ARCHDEF=PPC32 ;; + ppc64) ZERO_ARCHDEF=PPC64 ;; s390*) ZERO_ARCHDEF=S390 ;; sparc*) ZERO_ARCHDEF=SPARC ;; x86_64*) ZERO_ARCHDEF=AMD64 ;; diff --git a/common/bin/hgforest.sh b/common/bin/hgforest.sh index 5bf586bc13c..244881ae77c 100644 --- a/common/bin/hgforest.sh +++ b/common/bin/hgforest.sh @@ -106,12 +106,15 @@ if [ ${vflag} = "true" ] ; then echo "# Mercurial command: ${command}" > ${status_output} fi - -# capture command options and arguments (if any) -command_args="${@:-}" +# At this point all command options and args are in "$@". +# Always use "$@" (within double quotes) to avoid breaking +# args with spaces into separate args. if [ ${vflag} = "true" ] ; then - echo "# Mercurial command arguments: ${command_args}" > ${status_output} + echo "# Mercurial command argument count: $#" > ${status_output} + for cmdarg in "$@" ; do + echo "# Mercurial command argument: ${cmdarg}" > ${status_output} + done fi # Clean out the temporary directory that stores the pid files. @@ -205,13 +208,14 @@ if [ "${command}" = "clone" -o "${command}" = "fclone" -o "${command}" = "tclone pull_default_tail=`echo ${pull_default} | sed -e 's@^.*://[^/]*/\(.*\)@\1@'` - if [ -n "${command_args}" ] ; then + if [ $# -gt 0 ] ; then # if there is an "extra sources" path then reparent "extra" repos to that path if [ "x${pull_default}" = "x${pull_default_tail}" ] ; then echo "ERROR: Need initial clone from non-local source" > ${status_output} exit 1 fi - pull_extra="${command_args}/${pull_default_tail}" + # assume that "extra sources" path is the first arg + pull_extra="${1}/${pull_default_tail}" # determine which extra subrepos need to be cloned. for i in ${subrepos_extra} ; do @@ -356,8 +360,8 @@ else (PYTHONUNBUFFERED=true hg${global_opts} clone ${clone_newrepo} ${i}; echo "$?" > ${tmp}/${repopidfile}.pid.rc ) 2>&1 & else # run the command. - echo "cd ${i} && hg${global_opts} ${command} ${command_args}" > ${status_output} - cd ${i} && (PYTHONUNBUFFERED=true hg${global_opts} ${command} ${command_args}; echo "$?" > ${tmp}/${repopidfile}.pid.rc ) 2>&1 & + echo "cd ${i} && hg${global_opts} ${command} ${@}" > ${status_output} + cd ${i} && (PYTHONUNBUFFERED=true hg${global_opts} ${command} "${@}"; echo "$?" > ${tmp}/${repopidfile}.pid.rc ) 2>&1 & fi echo $! > ${tmp}/${repopidfile}.pid diff --git a/corba/.hgtags b/corba/.hgtags index 26c65ed70d5..3c3ea198849 100644 --- a/corba/.hgtags +++ b/corba/.hgtags @@ -285,3 +285,5 @@ ffd90c81d4ef9d94d880fc852e2fc482ecd9b374 jdk9-b36 e27c725d6c9d155667b35255f442d4ceb8c3c084 jdk9-b40 1908b886ba1eda46fa725cf1160fe5d30fd1a7e5 jdk9-b41 078bb11af876fe528d4b516f33ad4dd9bb60549e jdk9-b42 +9645e35616b60c5c07b4fdf11a132afc8081dfa8 jdk9-b43 +1f57bd728c9e6865ccb9d43ccd80a1c11230a32f jdk9-b44 diff --git a/hotspot/.hgtags b/hotspot/.hgtags index ae7d006d45b..ed88a27ff49 100644 --- a/hotspot/.hgtags +++ b/hotspot/.hgtags @@ -445,3 +445,5 @@ c363a8b87e477ee45d6d3cb2a36cb365141bc596 jdk9-b38 6b09b3193d731e3288e2a240c504a20d0a06c766 jdk9-b40 1d29b13e8a515a7ea3b882f140576d5d675bc11f jdk9-b41 38cb4fbd47e3472bd1b5ebac83bda96fe4869c4f jdk9-b42 +65a9747147b8090037541040ba67156ec914db6a jdk9-b43 +43a44b56dca61a4d766a20f0528fdd8b5ceff873 jdk9-b44 diff --git a/hotspot/agent/src/os/win32/windbg/sawindbg.cpp b/hotspot/agent/src/os/win32/windbg/sawindbg.cpp index f4a9b7922ba..647e4d62140 100644 --- a/hotspot/agent/src/os/win32/windbg/sawindbg.cpp +++ b/hotspot/agent/src/os/win32/windbg/sawindbg.cpp @@ -22,6 +22,9 @@ * */ +// Disable CRT security warning against strcpy/strcat +#pragma warning(disable: 4996) + // this is source code windbg based SA debugger agent to debug // Dr. Watson dump files and process snapshots. diff --git a/hotspot/agent/src/share/native/sadis.c b/hotspot/agent/src/share/native/sadis.c index 926b4e5fd55..69b4135e06b 100644 --- a/hotspot/agent/src/share/native/sadis.c +++ b/hotspot/agent/src/share/native/sadis.c @@ -33,6 +33,8 @@ */ #ifdef _WINDOWS +// Disable CRT security warning against _snprintf +#pragma warning (disable : 4996) #define snprintf _snprintf #define vsnprintf _vsnprintf @@ -90,12 +92,8 @@ static int getLastErrorString(char *buf, size_t len) if (errno != 0) { /* C runtime error that has no corresponding DOS error code */ - const char *s = strerror(errno); - size_t n = strlen(s); - if (n >= len) n = len - 1; - strncpy(buf, s, n); - buf[n] = '\0'; - return (int)n; + strerror_s(buf, len, errno); + return strlen(buf); } return 0; } @@ -111,16 +109,30 @@ JNIEXPORT jlong JNICALL Java_sun_jvm_hotspot_asm_Disassembler_load_1library(JNIE jstring jrepath_s, jstring libname_s) { uintptr_t func = 0; - const char* error_message = NULL; - jboolean isCopy; - - const char * jrepath = (*env)->GetStringUTFChars(env, jrepath_s, &isCopy); // like $JAVA_HOME/jre/lib/sparc/ - const char * libname = (*env)->GetStringUTFChars(env, libname_s, &isCopy); + const char *error_message = NULL; + const char *jrepath = NULL; + const char *libname = NULL; char buffer[128]; +#ifdef _WINDOWS + HINSTANCE hsdis_handle = (HINSTANCE) NULL; +#else + void* hsdis_handle = NULL; +#endif + + jrepath = (*env)->GetStringUTFChars(env, jrepath_s, NULL); // like $JAVA_HOME/jre/lib/sparc/ + if (jrepath == NULL || (*env)->ExceptionOccurred(env)) { + return 0; + } + + libname = (*env)->GetStringUTFChars(env, libname_s, NULL); + if (libname == NULL || (*env)->ExceptionOccurred(env)) { + (*env)->ReleaseStringUTFChars(env, jrepath_s, jrepath); + return 0; + } + /* Load the hsdis library */ #ifdef _WINDOWS - HINSTANCE hsdis_handle; hsdis_handle = LoadLibrary(libname); if (hsdis_handle == NULL) { snprintf(buffer, sizeof(buffer), "%s%s", jrepath, libname); @@ -134,7 +146,6 @@ JNIEXPORT jlong JNICALL Java_sun_jvm_hotspot_asm_Disassembler_load_1library(JNIE error_message = buffer; } #else - void* hsdis_handle; hsdis_handle = dlopen(libname, RTLD_LAZY | RTLD_GLOBAL); if (hsdis_handle == NULL) { snprintf(buffer, sizeof(buffer), "%s%s", jrepath, libname); @@ -156,6 +167,11 @@ JNIEXPORT jlong JNICALL Java_sun_jvm_hotspot_asm_Disassembler_load_1library(JNIE * platform dependent error message. */ jclass eclass = (*env)->FindClass(env, "sun/jvm/hotspot/debugger/DebuggerException"); + if ((*env)->ExceptionOccurred(env)) { + /* Can't throw exception, probably OOM, so silently return 0 */ + return (jlong) 0; + } + (*env)->ThrowNew(env, eclass, error_message); } return (jlong)func; @@ -184,16 +200,22 @@ typedef struct { /* event callback binding to Disassembler.handleEvent */ static void* event_to_env(void* env_pv, const char* event, void* arg) { + jlong result = 0; decode_env* denv = (decode_env*)env_pv; JNIEnv* env = denv->env; jstring event_string = (*env)->NewStringUTF(env, event); - jlong result = (*env)->CallLongMethod(env, denv->dis, denv->handle_event, denv->visitor, - event_string, (jlong) (uintptr_t)arg); - if ((*env)->ExceptionOccurred(env) != NULL) { + if ((*env)->ExceptionOccurred(env)) { + return NULL; + } + + result = (*env)->CallLongMethod(env, denv->dis, denv->handle_event, denv->visitor, + event_string, (jlong) (uintptr_t)arg); + if ((*env)->ExceptionOccurred(env)) { /* ignore exceptions for now */ (*env)->ExceptionClear(env); - result = 0; + return NULL; } + return (void*)(uintptr_t)result; } @@ -219,10 +241,13 @@ static int printf_to_env(void* env_pv, const char* format, ...) { } if (raw != NULL) { jstring output = (*env)->NewStringUTF(env, raw); - (*env)->CallVoidMethod(env, denv->dis, denv->raw_print, denv->visitor, output); - if ((*env)->ExceptionOccurred(env) != NULL) { + if (!(*env)->ExceptionOccurred(env)) { + /* make sure that UTF allocation doesn't cause OOM */ + (*env)->CallVoidMethod(env, denv->dis, denv->raw_print, denv->visitor, output); + } + if ((*env)->ExceptionOccurred(env)) { /* ignore exceptions for now */ - (*env)->ExceptionClear(env); + (*env)->ExceptionClear(env); } return (int) flen; } @@ -231,11 +256,16 @@ static int printf_to_env(void* env_pv, const char* format, ...) { va_end(ap); output = (*env)->NewStringUTF(env, denv->buffer); - (*env)->CallVoidMethod(env, denv->dis, denv->raw_print, denv->visitor, output); - if ((*env)->ExceptionOccurred(env) != NULL) { + if (!(*env)->ExceptionOccurred(env)) { + /* make sure that UTF allocation doesn't cause OOM */ + (*env)->CallVoidMethod(env, denv->dis, denv->raw_print, denv->visitor, output); + } + + if ((*env)->ExceptionOccurred(env)) { /* ignore exceptions for now */ (*env)->ExceptionClear(env); } + return cnt; } @@ -251,13 +281,24 @@ JNIEXPORT void JNICALL Java_sun_jvm_hotspot_asm_Disassembler_decode(JNIEnv * env jbyteArray code, jstring options_s, jlong decode_instructions_virtual) { - jboolean isCopy; - jbyte* start = (*env)->GetByteArrayElements(env, code, &isCopy); - jbyte* end = start + (*env)->GetArrayLength(env, code); - const char * options = (*env)->GetStringUTFChars(env, options_s, &isCopy); - jclass disclass = (*env)->GetObjectClass(env, dis); - + jbyte *start = NULL; + jbyte *end = NULL; + jclass disclass = NULL; + const char *options = NULL; decode_env denv; + + start = (*env)->GetByteArrayElements(env, code, NULL); + if ((*env)->ExceptionOccurred(env)) { + return; + } + end = start + (*env)->GetArrayLength(env, code); + options = (*env)->GetStringUTFChars(env, options_s, NULL); + if ((*env)->ExceptionOccurred(env)) { + (*env)->ReleaseByteArrayElements(env, code, start, JNI_ABORT); + return; + } + disclass = (*env)->GetObjectClass(env, dis); + denv.env = env; denv.dis = dis; denv.visitor = visitor; @@ -266,6 +307,8 @@ JNIEXPORT void JNICALL Java_sun_jvm_hotspot_asm_Disassembler_decode(JNIEnv * env denv.handle_event = (*env)->GetMethodID(env, disclass, "handleEvent", "(Lsun/jvm/hotspot/asm/InstructionVisitor;Ljava/lang/String;J)J"); if ((*env)->ExceptionOccurred(env)) { + (*env)->ReleaseByteArrayElements(env, code, start, JNI_ABORT); + (*env)->ReleaseStringUTFChars(env, options_s, options); return; } @@ -273,11 +316,13 @@ JNIEXPORT void JNICALL Java_sun_jvm_hotspot_asm_Disassembler_decode(JNIEnv * env denv.raw_print = (*env)->GetMethodID(env, disclass, "rawPrint", "(Lsun/jvm/hotspot/asm/InstructionVisitor;Ljava/lang/String;)V"); if ((*env)->ExceptionOccurred(env)) { + (*env)->ReleaseByteArrayElements(env, code, start, JNI_ABORT); + (*env)->ReleaseStringUTFChars(env, options_s, options); return; } /* decode the buffer */ - (*(decode_func)(uintptr_t)decode_instructions_virtual)(startPc, + (*(decode_func)(uintptr_t)decode_instructions_virtual)((uintptr_t) startPc, startPc + end - start, (unsigned char*)start, end - start, diff --git a/hotspot/make/aix/makefiles/mapfile-vers-debug b/hotspot/make/aix/makefiles/mapfile-vers-debug index 7ad34cd7aa9..348c128e434 100644 --- a/hotspot/make/aix/makefiles/mapfile-vers-debug +++ b/hotspot/make/aix/makefiles/mapfile-vers-debug @@ -72,7 +72,6 @@ SUNWprivate_1.1 { JVM_FillInStackTrace; JVM_FindClassFromCaller; JVM_FindClassFromClass; - JVM_FindClassFromClassLoader; JVM_FindClassFromBootLoader; JVM_FindLibraryEntry; JVM_FindLoadedClass; diff --git a/hotspot/make/aix/makefiles/mapfile-vers-product b/hotspot/make/aix/makefiles/mapfile-vers-product index 939600ac6e4..25bd5bfff7c 100644 --- a/hotspot/make/aix/makefiles/mapfile-vers-product +++ b/hotspot/make/aix/makefiles/mapfile-vers-product @@ -72,7 +72,6 @@ SUNWprivate_1.1 { JVM_FillInStackTrace; JVM_FindClassFromCaller; JVM_FindClassFromClass; - JVM_FindClassFromClassLoader; JVM_FindClassFromBootLoader; JVM_FindLibraryEntry; JVM_FindLoadedClass; diff --git a/hotspot/make/bsd/makefiles/mapfile-vers-darwin-debug b/hotspot/make/bsd/makefiles/mapfile-vers-darwin-debug index 231eb232ad1..ba3e771364c 100644 --- a/hotspot/make/bsd/makefiles/mapfile-vers-darwin-debug +++ b/hotspot/make/bsd/makefiles/mapfile-vers-darwin-debug @@ -70,7 +70,6 @@ _JVM_FillInStackTrace _JVM_FindClassFromCaller _JVM_FindClassFromClass - _JVM_FindClassFromClassLoader _JVM_FindClassFromBootLoader _JVM_FindLibraryEntry _JVM_FindLoadedClass diff --git a/hotspot/make/bsd/makefiles/mapfile-vers-darwin-product b/hotspot/make/bsd/makefiles/mapfile-vers-darwin-product index 231eb232ad1..ba3e771364c 100644 --- a/hotspot/make/bsd/makefiles/mapfile-vers-darwin-product +++ b/hotspot/make/bsd/makefiles/mapfile-vers-darwin-product @@ -70,7 +70,6 @@ _JVM_FillInStackTrace _JVM_FindClassFromCaller _JVM_FindClassFromClass - _JVM_FindClassFromClassLoader _JVM_FindClassFromBootLoader _JVM_FindLibraryEntry _JVM_FindLoadedClass diff --git a/hotspot/make/bsd/makefiles/mapfile-vers-debug b/hotspot/make/bsd/makefiles/mapfile-vers-debug index 0b72666e40b..fc05d864ad6 100644 --- a/hotspot/make/bsd/makefiles/mapfile-vers-debug +++ b/hotspot/make/bsd/makefiles/mapfile-vers-debug @@ -72,7 +72,6 @@ SUNWprivate_1.1 { JVM_FillInStackTrace; JVM_FindClassFromCaller; JVM_FindClassFromClass; - JVM_FindClassFromClassLoader; JVM_FindClassFromBootLoader; JVM_FindLibraryEntry; JVM_FindLoadedClass; diff --git a/hotspot/make/bsd/makefiles/mapfile-vers-product b/hotspot/make/bsd/makefiles/mapfile-vers-product index 0b72666e40b..fc05d864ad6 100644 --- a/hotspot/make/bsd/makefiles/mapfile-vers-product +++ b/hotspot/make/bsd/makefiles/mapfile-vers-product @@ -72,7 +72,6 @@ SUNWprivate_1.1 { JVM_FillInStackTrace; JVM_FindClassFromCaller; JVM_FindClassFromClass; - JVM_FindClassFromClassLoader; JVM_FindClassFromBootLoader; JVM_FindLibraryEntry; JVM_FindLoadedClass; diff --git a/hotspot/make/linux/makefiles/mapfile-vers-debug b/hotspot/make/linux/makefiles/mapfile-vers-debug index 0b72666e40b..fc05d864ad6 100644 --- a/hotspot/make/linux/makefiles/mapfile-vers-debug +++ b/hotspot/make/linux/makefiles/mapfile-vers-debug @@ -72,7 +72,6 @@ SUNWprivate_1.1 { JVM_FillInStackTrace; JVM_FindClassFromCaller; JVM_FindClassFromClass; - JVM_FindClassFromClassLoader; JVM_FindClassFromBootLoader; JVM_FindLibraryEntry; JVM_FindLoadedClass; diff --git a/hotspot/make/linux/makefiles/mapfile-vers-product b/hotspot/make/linux/makefiles/mapfile-vers-product index 0b72666e40b..fc05d864ad6 100644 --- a/hotspot/make/linux/makefiles/mapfile-vers-product +++ b/hotspot/make/linux/makefiles/mapfile-vers-product @@ -72,7 +72,6 @@ SUNWprivate_1.1 { JVM_FillInStackTrace; JVM_FindClassFromCaller; JVM_FindClassFromClass; - JVM_FindClassFromClassLoader; JVM_FindClassFromBootLoader; JVM_FindLibraryEntry; JVM_FindLoadedClass; diff --git a/hotspot/make/solaris/makefiles/mapfile-vers b/hotspot/make/solaris/makefiles/mapfile-vers index 77f878e1161..082b9f0e052 100644 --- a/hotspot/make/solaris/makefiles/mapfile-vers +++ b/hotspot/make/solaris/makefiles/mapfile-vers @@ -72,7 +72,6 @@ SUNWprivate_1.1 { JVM_FillInStackTrace; JVM_FindClassFromCaller; JVM_FindClassFromClass; - JVM_FindClassFromClassLoader; JVM_FindClassFromBootLoader; JVM_FindLibraryEntry; JVM_FindLoadedClass; diff --git a/hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.cpp b/hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.cpp index 6c89a18c03b..dec0d9732a8 100644 --- a/hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.cpp +++ b/hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.cpp @@ -544,6 +544,9 @@ void InterpreterMacroAssembler::index_check_without_pop(Register Rarray, Registe cmplw(CCR0, Rindex, Rlength); sldi(RsxtIndex, RsxtIndex, index_shift); blt(CCR0, LnotOOR); + // Index should be in R17_tos, array should be in R4_ARG2. + mr(R17_tos, Rindex); + mr(R4_ARG2, Rarray); load_dispatch_table(Rtmp, (address*)Interpreter::_throw_ArrayIndexOutOfBoundsException_entry); mtctr(Rtmp); bctr(); @@ -1678,6 +1681,228 @@ void InterpreterMacroAssembler::record_klass_in_profile_helper( } } +// Argument and return type profilig. +// kills: tmp, tmp2, R0, CR0, CR1 +void InterpreterMacroAssembler::profile_obj_type(Register obj, Register mdo_addr_base, + RegisterOrConstant mdo_addr_offs, Register tmp, Register tmp2) { + Label do_nothing, do_update; + + // tmp2 = obj is allowed + assert_different_registers(obj, mdo_addr_base, tmp, R0); + assert_different_registers(tmp2, mdo_addr_base, tmp, R0); + const Register klass = tmp2; + + verify_oop(obj); + + ld(tmp, mdo_addr_offs, mdo_addr_base); + + // Set null_seen if obj is 0. + cmpdi(CCR0, obj, 0); + ori(R0, tmp, TypeEntries::null_seen); + beq(CCR0, do_update); + + load_klass(klass, obj); + + clrrdi(R0, tmp, exact_log2(-TypeEntries::type_klass_mask)); + // Basically same as andi(R0, tmp, TypeEntries::type_klass_mask); + cmpd(CCR1, R0, klass); + // Klass seen before, nothing to do (regardless of unknown bit). + //beq(CCR1, do_nothing); + + andi_(R0, klass, TypeEntries::type_unknown); + // Already unknown. Nothing to do anymore. + //bne(CCR0, do_nothing); + crorc(/*CCR0 eq*/2, /*CCR1 eq*/4+2, /*CCR0 eq*/2); // cr0 eq = cr1 eq or cr0 ne + beq(CCR0, do_nothing); + + clrrdi_(R0, tmp, exact_log2(-TypeEntries::type_mask)); + orr(R0, klass, tmp); // Combine klass and null_seen bit (only used if (tmp & type_mask)==0). + beq(CCR0, do_update); // First time here. Set profile type. + + // Different than before. Cannot keep accurate profile. + ori(R0, tmp, TypeEntries::type_unknown); + + bind(do_update); + // update profile + std(R0, mdo_addr_offs, mdo_addr_base); + + align(32, 12); + bind(do_nothing); +} + +void InterpreterMacroAssembler::profile_arguments_type(Register callee, Register tmp1, Register tmp2, bool is_virtual) { + if (!ProfileInterpreter) { + return; + } + + assert_different_registers(callee, tmp1, tmp2, R28_mdx); + + if (MethodData::profile_arguments() || MethodData::profile_return()) { + Label profile_continue; + + test_method_data_pointer(profile_continue); + + int off_to_start = is_virtual ? in_bytes(VirtualCallData::virtual_call_data_size()) : in_bytes(CounterData::counter_data_size()); + + lbz(tmp1, in_bytes(DataLayout::tag_offset()) - off_to_start, R28_mdx); + cmpwi(CCR0, tmp1, is_virtual ? DataLayout::virtual_call_type_data_tag : DataLayout::call_type_data_tag); + bne(CCR0, profile_continue); + + if (MethodData::profile_arguments()) { + Label done; + int off_to_args = in_bytes(TypeEntriesAtCall::args_data_offset()); + add(R28_mdx, off_to_args, R28_mdx); + + for (int i = 0; i < TypeProfileArgsLimit; i++) { + if (i > 0 || MethodData::profile_return()) { + // If return value type is profiled we may have no argument to profile. + ld(tmp1, in_bytes(TypeEntriesAtCall::cell_count_offset())-off_to_args, R28_mdx); + cmpdi(CCR0, tmp1, (i+1)*TypeStackSlotEntries::per_arg_count()); + addi(tmp1, tmp1, -i*TypeStackSlotEntries::per_arg_count()); + blt(CCR0, done); + } + ld(tmp1, in_bytes(Method::const_offset()), callee); + lhz(tmp1, in_bytes(ConstMethod::size_of_parameters_offset()), tmp1); + // Stack offset o (zero based) from the start of the argument + // list, for n arguments translates into offset n - o - 1 from + // the end of the argument list. But there's an extra slot at + // the top of the stack. So the offset is n - o from Lesp. + ld(tmp2, in_bytes(TypeEntriesAtCall::stack_slot_offset(i))-off_to_args, R28_mdx); + subf(tmp1, tmp2, tmp1); + + sldi(tmp1, tmp1, Interpreter::logStackElementSize); + ldx(tmp1, tmp1, R15_esp); + + profile_obj_type(tmp1, R28_mdx, in_bytes(TypeEntriesAtCall::argument_type_offset(i))-off_to_args, tmp2, tmp1); + + int to_add = in_bytes(TypeStackSlotEntries::per_arg_size()); + addi(R28_mdx, R28_mdx, to_add); + off_to_args += to_add; + } + + if (MethodData::profile_return()) { + ld(tmp1, in_bytes(TypeEntriesAtCall::cell_count_offset())-off_to_args, R28_mdx); + addi(tmp1, tmp1, -TypeProfileArgsLimit*TypeStackSlotEntries::per_arg_count()); + } + + bind(done); + + if (MethodData::profile_return()) { + // We're right after the type profile for the last + // argument. tmp1 is the number of cells left in the + // CallTypeData/VirtualCallTypeData to reach its end. Non null + // if there's a return to profile. + assert(ReturnTypeEntry::static_cell_count() < TypeStackSlotEntries::per_arg_count(), "can't move past ret type"); + sldi(tmp1, tmp1, exact_log2(DataLayout::cell_size)); + add(R28_mdx, tmp1, R28_mdx); + } + } else { + assert(MethodData::profile_return(), "either profile call args or call ret"); + update_mdp_by_constant(in_bytes(TypeEntriesAtCall::return_only_size())); + } + + // Mdp points right after the end of the + // CallTypeData/VirtualCallTypeData, right after the cells for the + // return value type if there's one. + align(32, 12); + bind(profile_continue); + } +} + +void InterpreterMacroAssembler::profile_return_type(Register ret, Register tmp1, Register tmp2) { + assert_different_registers(ret, tmp1, tmp2); + if (ProfileInterpreter && MethodData::profile_return()) { + Label profile_continue; + + test_method_data_pointer(profile_continue); + + if (MethodData::profile_return_jsr292_only()) { + // If we don't profile all invoke bytecodes we must make sure + // it's a bytecode we indeed profile. We can't go back to the + // begining of the ProfileData we intend to update to check its + // type because we're right after it and we don't known its + // length. + lbz(tmp1, 0, R14_bcp); + lbz(tmp2, Method::intrinsic_id_offset_in_bytes(), R19_method); + cmpwi(CCR0, tmp1, Bytecodes::_invokedynamic); + cmpwi(CCR1, tmp1, Bytecodes::_invokehandle); + cror(/*CR0 eq*/2, /*CR1 eq*/4+2, /*CR0 eq*/2); + cmpwi(CCR1, tmp2, vmIntrinsics::_compiledLambdaForm); + cror(/*CR0 eq*/2, /*CR1 eq*/4+2, /*CR0 eq*/2); + bne(CCR0, profile_continue); + } + + profile_obj_type(ret, R28_mdx, -in_bytes(ReturnTypeEntry::size()), tmp1, tmp2); + + align(32, 12); + bind(profile_continue); + } +} + +void InterpreterMacroAssembler::profile_parameters_type(Register tmp1, Register tmp2, Register tmp3, Register tmp4) { + if (ProfileInterpreter && MethodData::profile_parameters()) { + Label profile_continue, done; + + test_method_data_pointer(profile_continue); + + // Load the offset of the area within the MDO used for + // parameters. If it's negative we're not profiling any parameters. + lwz(tmp1, in_bytes(MethodData::parameters_type_data_di_offset()) - in_bytes(MethodData::data_offset()), R28_mdx); + cmpwi(CCR0, tmp1, 0); + blt(CCR0, profile_continue); + + // Compute a pointer to the area for parameters from the offset + // and move the pointer to the slot for the last + // parameters. Collect profiling from last parameter down. + // mdo start + parameters offset + array length - 1 + + // Pointer to the parameter area in the MDO. + const Register mdp = tmp1; + add(mdp, tmp1, R28_mdx); + + // Pffset of the current profile entry to update. + const Register entry_offset = tmp2; + // entry_offset = array len in number of cells + ld(entry_offset, in_bytes(ArrayData::array_len_offset()), mdp); + + int off_base = in_bytes(ParametersTypeData::stack_slot_offset(0)); + assert(off_base % DataLayout::cell_size == 0, "should be a number of cells"); + + // entry_offset (number of cells) = array len - size of 1 entry + offset of the stack slot field + addi(entry_offset, entry_offset, -TypeStackSlotEntries::per_arg_count() + (off_base / DataLayout::cell_size)); + // entry_offset in bytes + sldi(entry_offset, entry_offset, exact_log2(DataLayout::cell_size)); + + Label loop; + align(32, 12); + bind(loop); + + // Load offset on the stack from the slot for this parameter. + ld(tmp3, entry_offset, mdp); + sldi(tmp3, tmp3, Interpreter::logStackElementSize); + neg(tmp3, tmp3); + // Read the parameter from the local area. + ldx(tmp3, tmp3, R18_locals); + + // Make entry_offset now point to the type field for this parameter. + int type_base = in_bytes(ParametersTypeData::type_offset(0)); + assert(type_base > off_base, "unexpected"); + addi(entry_offset, entry_offset, type_base - off_base); + + // Profile the parameter. + profile_obj_type(tmp3, mdp, entry_offset, tmp4, tmp3); + + // Go to next parameter. + int delta = TypeStackSlotEntries::per_arg_count() * DataLayout::cell_size + (type_base - off_base); + cmpdi(CCR0, entry_offset, off_base + delta); + addi(entry_offset, entry_offset, -delta); + bge(CCR0, loop); + + align(32, 12); + bind(profile_continue); + } +} + // Add a InterpMonitorElem to stack (see frame_sparc.hpp). void InterpreterMacroAssembler::add_monitor_to_stack(bool stack_is_empty, Register Rtemp1, Register Rtemp2) { @@ -2039,20 +2264,19 @@ void InterpreterMacroAssembler::verify_oop_or_return_address(Register reg, Regis bne(CCR0, test); address fd = CAST_FROM_FN_PTR(address, verify_return_address); - unsigned int nbytes_save = 10*8; // 10 volatile gprs - - save_LR_CR(Rtmp); + const int nbytes_save = 11*8; // volatile gprs except R0 + save_volatile_gprs(R1_SP, -nbytes_save); // except R0 + save_LR_CR(Rtmp); // Save in old frame. push_frame_reg_args(nbytes_save, Rtmp); - save_volatile_gprs(R1_SP, 112); // except R0 load_const_optimized(Rtmp, fd, R0); mr_if_needed(R4_ARG2, reg); mr(R3_ARG1, R19_method); call_c(Rtmp); // call C - restore_volatile_gprs(R1_SP, 112); // except R0 pop_frame(); restore_LR_CR(Rtmp); + restore_volatile_gprs(R1_SP, -nbytes_save); // except R0 b(skip); // Perform a more elaborate out-of-line call. diff --git a/hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.hpp b/hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.hpp index 37c743228e9..555cc5ee9d8 100644 --- a/hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.hpp +++ b/hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.hpp @@ -255,6 +255,12 @@ class InterpreterMacroAssembler: public MacroAssembler { void record_klass_in_profile(Register receiver, Register scratch1, Register scratch2, bool is_virtual_call); void record_klass_in_profile_helper(Register receiver, Register scratch1, Register scratch2, int start_row, Label& done, bool is_virtual_call); + // Argument and return type profiling. + void profile_obj_type(Register obj, Register mdo_addr_base, RegisterOrConstant mdo_addr_offs, Register tmp, Register tmp2); + void profile_arguments_type(Register callee, Register tmp1, Register tmp2, bool is_virtual); + void profile_return_type(Register ret, Register tmp1, Register tmp2); + void profile_parameters_type(Register tmp1, Register tmp2, Register tmp3, Register tmp4); + #endif // !CC_INTERP // Debugging diff --git a/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp b/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp index 1b98de177dc..b0d4280a4d3 100644 --- a/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp +++ b/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp @@ -807,6 +807,7 @@ void MacroAssembler::restore_nonvolatile_gprs(Register src, int offset) { // For verify_oops. void MacroAssembler::save_volatile_gprs(Register dst, int offset) { + std(R2, offset, dst); offset += 8; std(R3, offset, dst); offset += 8; std(R4, offset, dst); offset += 8; std(R5, offset, dst); offset += 8; @@ -821,6 +822,7 @@ void MacroAssembler::save_volatile_gprs(Register dst, int offset) { // For verify_oops. void MacroAssembler::restore_volatile_gprs(Register src, int offset) { + ld(R2, offset, src); offset += 8; ld(R3, offset, src); offset += 8; ld(R4, offset, src); offset += 8; ld(R5, offset, src); offset += 8; @@ -1187,6 +1189,16 @@ void MacroAssembler::call_VM(Register oop_result, address entry_point, Register call_VM(oop_result, entry_point, check_exceptions); } +void MacroAssembler::call_VM(Register oop_result, address entry_point, Register arg_1, Register arg_2, Register arg_3, + bool check_exceptions) { + // R3_ARG1 is reserved for the thread + mr_if_needed(R4_ARG2, arg_1); + assert(arg_2 != R4_ARG2, "smashed argument"); + mr_if_needed(R5_ARG3, arg_2); + mr_if_needed(R6_ARG4, arg_3); + call_VM(oop_result, entry_point, check_exceptions); +} + void MacroAssembler::call_VM_leaf(address entry_point) { call_VM_leaf_base(entry_point); } @@ -3059,35 +3071,27 @@ void MacroAssembler::verify_oop(Register oop, const char* msg) { if (!VerifyOops) { return; } - // Will be preserved. - Register tmp = R11; - assert(oop != tmp, "precondition"); - unsigned int nbytes_save = 10*8; // 10 volatile gprs + address/* FunctionDescriptor** */fd = StubRoutines::verify_oop_subroutine_entry_address(); - // save tmp - mr(R0, tmp); - // kill tmp - save_LR_CR(tmp); + const Register tmp = R11; // Will be preserved. + const int nbytes_save = 11*8; // Volatile gprs except R0. + save_volatile_gprs(R1_SP, -nbytes_save); // except R0 + + if (oop == tmp) mr(R4_ARG2, oop); + save_LR_CR(tmp); // save in old frame push_frame_reg_args(nbytes_save, tmp); - // restore tmp - mr(tmp, R0); - save_volatile_gprs(R1_SP, 112); // except R0 // load FunctionDescriptor** / entry_address * - load_const(tmp, fd); + load_const_optimized(tmp, fd, R0); // load FunctionDescriptor* / entry_address ld(tmp, 0, tmp); - mr(R4_ARG2, oop); - load_const(R3_ARG1, (address)msg); - // call destination for its side effect + if (oop != tmp) mr_if_needed(R4_ARG2, oop); + load_const_optimized(R3_ARG1, (address)msg, R0); + // Call destination for its side effect. call_c(tmp); - restore_volatile_gprs(R1_SP, 112); // except R0 + pop_frame(); - // save tmp - mr(R0, tmp); - // kill tmp restore_LR_CR(tmp); - // restore tmp - mr(tmp, R0); + restore_volatile_gprs(R1_SP, -nbytes_save); // except R0 } const char* stop_types[] = { diff --git a/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.hpp b/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.hpp index 66e33888223..5c118981415 100644 --- a/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.hpp +++ b/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.hpp @@ -369,6 +369,7 @@ class MacroAssembler: public Assembler { void call_VM(Register oop_result, address entry_point, bool check_exceptions = true); void call_VM(Register oop_result, address entry_point, Register arg_1, bool check_exceptions = true); void call_VM(Register oop_result, address entry_point, Register arg_1, Register arg_2, bool check_exceptions = true); + void call_VM(Register oop_result, address entry_point, Register arg_1, Register arg_2, Register arg3, bool check_exceptions = true); void call_VM_leaf(address entry_point); void call_VM_leaf(address entry_point, Register arg_1); void call_VM_leaf(address entry_point, Register arg_1, Register arg_2); diff --git a/hotspot/src/cpu/ppc/vm/nativeInst_ppc.cpp b/hotspot/src/cpu/ppc/vm/nativeInst_ppc.cpp index 6f40af06f40..6a8b9a479af 100644 --- a/hotspot/src/cpu/ppc/vm/nativeInst_ppc.cpp +++ b/hotspot/src/cpu/ppc/vm/nativeInst_ppc.cpp @@ -100,10 +100,7 @@ void NativeCall::set_destination_mt_safe(address dest, bool assert_lock) { MacroAssembler* a = new MacroAssembler(&cb); // Patch the call. - if (ReoptimizeCallSequences && - a->is_within_range_of_b(dest, addr_call)) { - a->bl(dest); - } else { + if (!ReoptimizeCallSequences || !a->is_within_range_of_b(dest, addr_call)) { address trampoline_stub_addr = get_trampoline(); // We did not find a trampoline stub because the current codeblob @@ -115,9 +112,12 @@ void NativeCall::set_destination_mt_safe(address dest, bool assert_lock) { // Patch the constant in the call's trampoline stub. NativeCallTrampolineStub_at(trampoline_stub_addr)->set_destination(dest); - - a->bl(trampoline_stub_addr); + dest = trampoline_stub_addr; } + + OrderAccess::release(); + a->bl(dest); + ICache::ppc64_flush_icache_bytes(addr_call, code_size); } diff --git a/hotspot/src/cpu/ppc/vm/ppc.ad b/hotspot/src/cpu/ppc/vm/ppc.ad index d68749c8ca1..51a9762e983 100644 --- a/hotspot/src/cpu/ppc/vm/ppc.ad +++ b/hotspot/src/cpu/ppc/vm/ppc.ad @@ -1936,8 +1936,9 @@ ArchOpcode MachSpillCopyNode_archOpcode(MachSpillCopyNode *n, PhaseRegAlloc *ra_ // -------------------------------------------------------------------- // Check for hi bits still needing moving. Only happens for misaligned // arguments to native calls. - if (src_hi == dst_hi) + if (src_hi == dst_hi) { return ppc64Opcode_none; // Self copy; no move. + } ShouldNotReachHere(); return ppc64Opcode_undefined; @@ -1959,14 +1960,15 @@ void MachNopNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *) const { } uint MachNopNode::size(PhaseRegAlloc *ra_) const { - return _count * 4; + return _count * 4; } #ifndef PRODUCT void BoxLockNode::format(PhaseRegAlloc *ra_, outputStream *st) const { int offset = ra_->reg2offset(in_RegMask(0).find_first_elem()); - int reg = ra_->get_reg_first(this); - st->print("ADDI %s, SP, %d \t// box node", Matcher::regName[reg], offset); + char reg_str[128]; + ra_->dump_register(this, reg_str); + st->print("ADDI %s, SP, %d \t// box node", reg_str, offset); } #endif diff --git a/hotspot/src/cpu/ppc/vm/templateInterpreter_ppc.cpp b/hotspot/src/cpu/ppc/vm/templateInterpreter_ppc.cpp index c53d73ec890..2a58b36d420 100644 --- a/hotspot/src/cpu/ppc/vm/templateInterpreter_ppc.cpp +++ b/hotspot/src/cpu/ppc/vm/templateInterpreter_ppc.cpp @@ -91,7 +91,7 @@ address TemplateInterpreterGenerator::generate_ClassCastException_verbose_handle // Thread will be loaded to R3_ARG1. // Target class oop is in register R5_ARG3 by convention! - __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_ClassCastException_verbose, R17_tos, R5_ARG3)); + __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_ClassCastException_verbose), R17_tos, R5_ARG3); // Above call must not return here since exception pending. DEBUG_ONLY(__ should_not_reach_here();) return entry; @@ -172,6 +172,10 @@ address TemplateInterpreterGenerator::generate_return_entry_for(TosState state, // Compiled code destroys templateTableBase, reload. __ load_const_optimized(R25_templateTableBase, (address)Interpreter::dispatch_table((TosState)0), R12_scratch2); + if (state == atos) { + __ profile_return_type(R3_RET, R11_scratch1, R12_scratch2); + } + const Register cache = R11_scratch1; const Register size = R12_scratch2; __ get_cache_and_index_at_bcp(cache, 1, index_size); @@ -1189,6 +1193,10 @@ address TemplateInterpreterGenerator::generate_normal_entry(bool synchronized) { __ li(R0, 1); __ stb(R0, in_bytes(JavaThread::do_not_unlock_if_synchronized_offset()), R16_thread); } + + // Argument and return type profiling. + __ profile_parameters_type(R3_ARG1, R4_ARG2, R5_ARG3, R6_ARG4); + // Increment invocation counter and check for overflow. if (inc_counter) { generate_counter_incr(&invocation_counter_overflow, &profile_method, &profile_method_continue); @@ -1469,6 +1477,8 @@ void TemplateInterpreterGenerator::generate_throw_exception() { __ resize_frame_absolute(R12_scratch2, R11_scratch1, R0); if (ProfileInterpreter) { __ set_method_data_pointer_for_bcp(); + __ ld(R11_scratch1, 0, R1_SP); + __ std(R28_mdx, _ijava_state_neg(mdx), R11_scratch1); } #if INCLUDE_JVMTI Label L_done; @@ -1480,13 +1490,11 @@ void TemplateInterpreterGenerator::generate_throw_exception() { // The member name argument must be restored if _invokestatic is re-executed after a PopFrame call. // Detect such a case in the InterpreterRuntime function and return the member name argument, or NULL. __ ld(R4_ARG2, 0, R18_locals); - __ call_VM(R11_scratch1, CAST_FROM_FN_PTR(address, InterpreterRuntime::member_name_arg_or_null), - R4_ARG2, R19_method, R14_bcp); - - __ cmpdi(CCR0, R11_scratch1, 0); + __ MacroAssembler::call_VM(R4_ARG2, CAST_FROM_FN_PTR(address, InterpreterRuntime::member_name_arg_or_null), R4_ARG2, R19_method, R14_bcp, false); + __ restore_interpreter_state(R11_scratch1, /*bcp_and_mdx_only*/ true); + __ cmpdi(CCR0, R4_ARG2, 0); __ beq(CCR0, L_done); - - __ std(R11_scratch1, wordSize, R15_esp); + __ std(R4_ARG2, wordSize, R15_esp); __ bind(L_done); #endif // INCLUDE_JVMTI __ dispatch_next(vtos); diff --git a/hotspot/src/cpu/ppc/vm/templateTable_ppc_64.cpp b/hotspot/src/cpu/ppc/vm/templateTable_ppc_64.cpp index bf8f5ead1c9..40cd339c2c0 100644 --- a/hotspot/src/cpu/ppc/vm/templateTable_ppc_64.cpp +++ b/hotspot/src/cpu/ppc/vm/templateTable_ppc_64.cpp @@ -3235,6 +3235,8 @@ void TemplateTable::generate_vtable_call(Register Rrecv_klass, Register Rindex, // Load target. __ addi(Rrecv_klass, Rrecv_klass, base + vtableEntry::method_offset_in_bytes()); __ ldx(Rtarget_method, Rindex, Rrecv_klass); + // Argument and return type profiling. + __ profile_arguments_type(Rtarget_method, Rrecv_klass /* scratch1 */, Rtemp /* scratch2 */, true); __ call_from_interpreter(Rtarget_method, Rret, Rrecv_klass /* scratch1 */, Rtemp /* scratch2 */); } @@ -3318,6 +3320,8 @@ void TemplateTable::invokevfinal_helper(Register Rmethod, Register Rflags, Regis __ null_check_throw(Rrecv, -1, Rscratch1); __ profile_final_call(Rrecv, Rscratch1); + // Argument and return type profiling. + __ profile_arguments_type(Rmethod, Rscratch1, Rscratch2, true); // Do the call. __ call_from_interpreter(Rmethod, Rret_addr, Rscratch1, Rscratch2); @@ -3339,6 +3343,8 @@ void TemplateTable::invokespecial(int byte_no) { __ null_check_throw(Rreceiver, -1, R11_scratch1); __ profile_call(R11_scratch1, R12_scratch2); + // Argument and return type profiling. + __ profile_arguments_type(Rmethod, R11_scratch1, R12_scratch2, false); __ call_from_interpreter(Rmethod, Rret_addr, R11_scratch1, R12_scratch2); } @@ -3353,6 +3359,8 @@ void TemplateTable::invokestatic(int byte_no) { prepare_invoke(byte_no, R19_method, Rret_addr, noreg, noreg, Rflags, R11_scratch1); __ profile_call(R11_scratch1, R12_scratch2); + // Argument and return type profiling. + __ profile_arguments_type(R19_method, R11_scratch1, R12_scratch2, false); __ call_from_interpreter(R19_method, Rret_addr, R11_scratch1, R12_scratch2); } @@ -3374,6 +3382,8 @@ void TemplateTable::invokeinterface_object_method(Register Rrecv_klass, // Final call case. __ profile_final_call(Rtemp1, Rscratch); + // Argument and return type profiling. + __ profile_arguments_type(Rindex, Rscratch, Rrecv_klass /* scratch */, true); // Do the final call - the index (f2) contains the method. __ call_from_interpreter(Rindex, Rret, Rscratch, Rrecv_klass /* scratch */); @@ -3425,6 +3435,8 @@ void TemplateTable::invokeinterface(int byte_no) { __ cmpdi(CCR0, Rindex, 0); __ beq(CCR0, Lthrow_ame); // Found entry. Jump off! + // Argument and return type profiling. + __ profile_arguments_type(Rindex, Rscratch1, Rscratch2, true); __ call_from_interpreter(Rindex, Rret_addr, Rscratch1, Rscratch2); // Vtable entry was NULL => Throw abstract method error. @@ -3468,6 +3480,8 @@ void TemplateTable::invokedynamic(int byte_no) { // to be the callsite object the bootstrap method returned. This is passed to a // "link" method which does the dispatch (Most likely just grabs the MH stored // inside the callsite and does an invokehandle). + // Argument and return type profiling. + __ profile_arguments_type(Rmethod, Rscratch1, Rscratch2, false); __ call_from_interpreter(Rmethod, Rret_addr, Rscratch1 /* scratch1 */, Rscratch2 /* scratch2 */); } @@ -3488,6 +3502,8 @@ void TemplateTable::invokehandle(int byte_no) { __ profile_final_call(Rrecv, Rscratch1); // Still no call from handle => We call the method handle interpreter here. + // Argument and return type profiling. + __ profile_arguments_type(Rmethod, Rscratch1, Rscratch2, true); __ call_from_interpreter(Rmethod, Rret_addr, Rscratch1 /* scratch1 */, Rscratch2 /* scratch2 */); } diff --git a/hotspot/src/cpu/ppc/vm/vm_version_ppc.cpp b/hotspot/src/cpu/ppc/vm/vm_version_ppc.cpp index 0e66115a3f8..60f26c5f1c1 100644 --- a/hotspot/src/cpu/ppc/vm/vm_version_ppc.cpp +++ b/hotspot/src/cpu/ppc/vm/vm_version_ppc.cpp @@ -134,13 +134,44 @@ void VM_Version::initialize() { } assert(AllocatePrefetchLines > 0, "invalid value"); - if (AllocatePrefetchLines < 1) // Set valid value in product VM. + if (AllocatePrefetchLines < 1) { // Set valid value in product VM. AllocatePrefetchLines = 1; // Conservative value. + } - if (AllocatePrefetchStyle == 3 && AllocatePrefetchDistance < cache_line_size) + if (AllocatePrefetchStyle == 3 && AllocatePrefetchDistance < cache_line_size) { AllocatePrefetchStyle = 1; // Fall back if inappropriate. + } assert(AllocatePrefetchStyle >= 0, "AllocatePrefetchStyle should be positive"); + + if (UseCRC32Intrinsics) { + if (!FLAG_IS_DEFAULT(UseCRC32Intrinsics)) + warning("CRC32 intrinsics are not available on this CPU"); + FLAG_SET_DEFAULT(UseCRC32Intrinsics, false); + } + + // The AES intrinsic stubs require AES instruction support. + if (UseAES) { + warning("AES instructions are not available on this CPU"); + FLAG_SET_DEFAULT(UseAES, false); + } + if (UseAESIntrinsics) { + if (!FLAG_IS_DEFAULT(UseAESIntrinsics)) + warning("AES intrinsics are not available on this CPU"); + FLAG_SET_DEFAULT(UseAESIntrinsics, false); + } + + if (UseSHA) { + warning("SHA instructions are not available on this CPU"); + FLAG_SET_DEFAULT(UseSHA, false); + } + if (UseSHA1Intrinsics || UseSHA256Intrinsics || UseSHA512Intrinsics) { + warning("SHA intrinsics are not available on this CPU"); + FLAG_SET_DEFAULT(UseSHA1Intrinsics, false); + FLAG_SET_DEFAULT(UseSHA256Intrinsics, false); + FLAG_SET_DEFAULT(UseSHA512Intrinsics, false); + } + } void VM_Version::print_features() { diff --git a/hotspot/src/cpu/x86/vm/c1_Runtime1_x86.cpp b/hotspot/src/cpu/x86/vm/c1_Runtime1_x86.cpp index a0d54665375..63da256a7a9 100644 --- a/hotspot/src/cpu/x86/vm/c1_Runtime1_x86.cpp +++ b/hotspot/src/cpu/x86/vm/c1_Runtime1_x86.cpp @@ -675,7 +675,7 @@ OopMapSet* Runtime1::generate_handle_exception(StubID id, StubAssembler *sasm) { case handle_exception_nofpu_id: case handle_exception_id: // At this point all registers MAY be live. - oop_map = save_live_registers(sasm, 1 /*thread*/, id == handle_exception_nofpu_id); + oop_map = save_live_registers(sasm, 1 /*thread*/, id != handle_exception_nofpu_id); break; case handle_exception_from_callee_id: { // At this point all registers except exception oop (RAX) and @@ -748,7 +748,7 @@ OopMapSet* Runtime1::generate_handle_exception(StubID id, StubAssembler *sasm) { case handle_exception_nofpu_id: case handle_exception_id: // Restore the registers that were saved at the beginning. - restore_live_registers(sasm, id == handle_exception_nofpu_id); + restore_live_registers(sasm, id != handle_exception_nofpu_id); break; case handle_exception_from_callee_id: // WIN64_ONLY: No need to add frame::arg_reg_save_area_bytes to SP diff --git a/hotspot/src/os/aix/vm/osThread_aix.cpp b/hotspot/src/os/aix/vm/osThread_aix.cpp index 5c56387163c..ef6c973e3fe 100644 --- a/hotspot/src/os/aix/vm/osThread_aix.cpp +++ b/hotspot/src/os/aix/vm/osThread_aix.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved. * Copyright 2012, 2013 SAP AG. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -45,7 +45,8 @@ void OSThread::pd_initialize() { sigemptyset(&_caller_sigmask); - _startThread_lock = new Monitor(Mutex::event, "startThread_lock", true); + _startThread_lock = new Monitor(Mutex::event, "startThread_lock", true, + Monitor::_safepoint_check_never); assert(_startThread_lock !=NULL, "check"); } diff --git a/hotspot/src/os/aix/vm/os_aix.cpp b/hotspot/src/os/aix/vm/os_aix.cpp index 2a77a9e80f6..e3322ca0364 100644 --- a/hotspot/src/os/aix/vm/os_aix.cpp +++ b/hotspot/src/os/aix/vm/os_aix.cpp @@ -124,12 +124,6 @@ extern "C" { } #endif -// Excerpts from systemcfg.h definitions newer than AIX 5.3 -#ifndef PV_7 -# define PV_7 0x200000 // Power PC 7 -# define PV_7_Compat 0x208000 // Power PC 7 -#endif - #define MAX_PATH (2 * K) // for timer info max values which include all bits @@ -140,17 +134,40 @@ extern "C" { #define ERROR_MP_VMGETINFO_FAILED 102 #define ERROR_MP_VMGETINFO_CLAIMS_NO_SUPPORT_FOR_64K 103 -// the semantics in this file are thus that codeptr_t is a *real code ptr* +// The semantics in this file are thus that codeptr_t is a *real code ptr*. // This means that any function taking codeptr_t as arguments will assume // a real codeptr and won't handle function descriptors (eg getFuncName), // whereas functions taking address as args will deal with function -// descriptors (eg os::dll_address_to_library_name) +// descriptors (eg os::dll_address_to_library_name). typedef unsigned int* codeptr_t; -// typedefs for stackslots, stack pointers, pointers to op codes +// Typedefs for stackslots, stack pointers, pointers to op codes. typedef unsigned long stackslot_t; typedef stackslot_t* stackptr_t; +// Excerpts from systemcfg.h definitions newer than AIX 5.3. +#ifndef PV_7 +#define PV_7 0x200000 /* Power PC 7 */ +#define PV_7_Compat 0x208000 /* Power PC 7 */ +#endif +#ifndef PV_8 +#define PV_8 0x300000 /* Power PC 8 */ +#define PV_8_Compat 0x308000 /* Power PC 8 */ +#endif + +#define trcVerbose(fmt, ...) { /* PPC port */ \ + if (Verbose) { \ + fprintf(stderr, fmt, ##__VA_ARGS__); \ + fputc('\n', stderr); fflush(stderr); \ + } \ +} +#define trc(fmt, ...) /* PPC port */ + +#define ERRBYE(s) { \ + trcVerbose(s); \ + return -1; \ +} + // query dimensions of the stack of the calling thread static void query_stack_dimensions(address* p_stack_base, size_t* p_stack_size); @@ -182,12 +199,12 @@ inline bool is_valid_codepointer(codeptr_t p) { return true; } -// macro to check a given stack pointer against given stack limits and to die if test fails +// Macro to check a given stack pointer against given stack limits and to die if test fails. #define CHECK_STACK_PTR(sp, stack_base, stack_size) { \ guarantee(is_valid_stackpointer((stackptr_t)(sp), (stackptr_t)(stack_base), stack_size), "Stack Pointer Invalid"); \ } -// macro to check the current stack pointer against given stacklimits +// Macro to check the current stack pointer against given stacklimits. #define CHECK_CURRENT_STACK_PTR(stack_base, stack_size) { \ address sp; \ sp = os::current_stack_pointer(); \ @@ -221,7 +238,7 @@ static bool check_signals = true; static pid_t _initial_pid = 0; static int SR_signum = SIGUSR2; // Signal used to suspend/resume a thread (must be > SIGSEGV, see 4355769) static sigset_t SR_sigset; -static pthread_mutex_t dl_mutex; // Used to protect dlsym() calls */ +static pthread_mutex_t dl_mutex; // Used to protect dlsym() calls. julong os::available_memory() { return Aix::available_memory(); @@ -253,7 +270,6 @@ bool os::getenv(const char* name, char* buf, int len) { return false; } - // Return true if user is running as root. bool os::have_special_privileges() { @@ -284,8 +300,7 @@ static bool my_disclaim64(char* addr, size_t size) { for (int i = 0; i < numFullDisclaimsNeeded; i ++) { if (::disclaim(p, maxDisclaimSize, DISCLAIM_ZEROMEM) != 0) { - //if (Verbose) - fprintf(stderr, "Cannot disclaim %p - %p (errno %d)\n", p, p + maxDisclaimSize, errno); + trc("Cannot disclaim %p - %p (errno %d)\n", p, p + maxDisclaimSize, errno); return false; } p += maxDisclaimSize; @@ -293,8 +308,7 @@ static bool my_disclaim64(char* addr, size_t size) { if (lastDisclaimSize > 0) { if (::disclaim(p, lastDisclaimSize, DISCLAIM_ZEROMEM) != 0) { - //if (Verbose) - fprintf(stderr, "Cannot disclaim %p - %p (errno %d)\n", p, p + lastDisclaimSize, errno); + trc("Cannot disclaim %p - %p (errno %d)\n", p, p + lastDisclaimSize, errno); return false; } } @@ -334,11 +348,11 @@ pid_t os::Aix::gettid() { void os::Aix::initialize_system_info() { - // get the number of online(logical) cpus instead of configured + // Get the number of online(logical) cpus instead of configured. os::_processor_count = sysconf(_SC_NPROCESSORS_ONLN); assert(_processor_count > 0, "_processor_count must be > 0"); - // retrieve total physical storage + // Retrieve total physical storage. os::Aix::meminfo_t mi; if (!os::Aix::get_meminfo(&mi)) { fprintf(stderr, "os::Aix::get_meminfo failed.\n"); fflush(stderr); @@ -513,7 +527,6 @@ query_multipage_support_end: } // end os::Aix::query_multipage_support() -// The code for this method was initially derived from the version in os_linux.cpp. void os::init_system_properties_values() { #define DEFAULT_LIBPATH "/usr/lib:/lib" @@ -603,10 +616,11 @@ bool os::Aix::is_sig_ignored(int sig) { sigaction(sig, (struct sigaction*)NULL, &oact); void* ohlr = oact.sa_sigaction ? CAST_FROM_FN_PTR(void*, oact.sa_sigaction) : CAST_FROM_FN_PTR(void*, oact.sa_handler); - if (ohlr == CAST_FROM_FN_PTR(void*, SIG_IGN)) + if (ohlr == CAST_FROM_FN_PTR(void*, SIG_IGN)) { return true; - else + } else { return false; + } } void os::Aix::signal_sets_init() { @@ -780,6 +794,9 @@ bool os::Aix::get_cpuinfo(cpuinfo_t* pci) { // get the processor version from _system_configuration switch (_system_configuration.version) { + case PV_8: + strcpy(pci->version, "Power PC 8"); + break; case PV_7: strcpy(pci->version, "Power PC 7"); break; @@ -807,6 +824,9 @@ bool os::Aix::get_cpuinfo(cpuinfo_t* pci) { case PV_7_Compat: strcpy(pci->version, "PV_7_Compat"); break; + case PV_8_Compat: + strcpy(pci->version, "PV_8_Compat"); + break; default: strcpy(pci->version, "unknown"); } @@ -942,7 +962,9 @@ bool os::create_thread(Thread* thread, ThreadType thr_type, size_t stack_size) { pthread_attr_destroy(&attr); - if (ret != 0) { + if (ret == 0) { + // PPC port traceOsMisc(("Created New Thread : pthread-id %u", tid)); + } else { if (PrintMiscellaneous && (Verbose || WizardMode)) { perror("pthread_create()"); } @@ -1103,8 +1125,7 @@ jlong os::javaTimeNanos() { if (os::Aix::on_pase()) { Unimplemented(); return 0; - } - else { + } else { // On AIX use the precision of processors real time clock // or time base registers. timebasestruct_t time; @@ -1152,7 +1173,6 @@ bool os::getTimesSecs(double* process_real_time, } } - char * os::local_time_string(char *buf, size_t buflen) { struct tm t; time_t long_time; @@ -1190,7 +1210,6 @@ void os::shutdown() { if (abort_hook != NULL) { abort_hook(); } - } // Note: os::abort() might be called very early during initialization, or @@ -1222,8 +1241,7 @@ void os::die() { // from src/solaris/hpi/src/system_md.c size_t os::lasterror(char *buf, size_t len) { - - if (errno == 0) return 0; + if (errno == 0) return 0; const char *s = ::strerror(errno); size_t n = ::strlen(s); @@ -1236,6 +1254,7 @@ size_t os::lasterror(char *buf, size_t len) { } intx os::current_thread_id() { return (intx)pthread_self(); } + int os::current_process_id() { // This implementation returns a unique pid, the pid of the @@ -1372,9 +1391,9 @@ bool os::dll_address_to_function_name(address addr, char *buf, if (offset) { *offset = -1; } - if (buf) { - buf[0] = '\0'; - } + // Buf is not optional, but offset is optional. + assert(buf != NULL, "sanity check"); + buf[0] = '\0'; // Resolve function ptr literals first. addr = resolve_function_descriptor_to_code_pointer(addr); @@ -1407,12 +1426,9 @@ static int getModuleName(codeptr_t pc, // [in] program counte return 0; } - if (Verbose) { - fprintf(stderr, "pc outside any module"); - } + trcVerbose("pc outside any module"); return -1; - } bool os::dll_address_to_library_name(address addr, char* buf, @@ -1420,9 +1436,9 @@ bool os::dll_address_to_library_name(address addr, char* buf, if (offset) { *offset = -1; } - if (buf) { - buf[0] = '\0'; - } + // Buf is not optional, but offset is optional. + assert(buf != NULL, "sanity check"); + buf[0] = '\0'; // Resolve function ptr literals first. addr = resolve_function_descriptor_to_code_pointer(addr); @@ -1437,7 +1453,7 @@ bool os::dll_address_to_library_name(address addr, char* buf, } // Loads .dll/.so and in case of error it checks if .dll/.so was built -// for the same architecture as Hotspot is running on +// for the same architecture as Hotspot is running on. void *os::dll_load(const char *filename, char *ebuf, int ebuflen) { if (ebuf && ebuflen > 0) { @@ -1600,7 +1616,6 @@ void os::print_siginfo(outputStream* st, void* siginfo) { st->cr(); } - static void print_signal_handler(outputStream* st, int sig, char* buf, size_t buflen); @@ -1624,7 +1639,7 @@ void os::print_signal_handlers(outputStream* st, char* buf, size_t buflen) { static char saved_jvm_path[MAXPATHLEN] = {0}; -// Find the full path to the current module, libjvm.so or libjvm_g.so +// Find the full path to the current module, libjvm.so. void os::jvm_path(char *buf, jint buflen) { // Error checking. if (buflen < MAXPATHLEN) { @@ -1695,7 +1710,7 @@ void* os::signal(int signal_number, void* handler) { // Do not block out synchronous signals in the signal handler. // Blocking synchronous signals only makes sense if you can really // be sure that those signals won't happen during signal handling, - // when the blocking applies. Normal signal handlers are lean and + // when the blocking applies. Normal signal handlers are lean and // do not cause signals. But our signal handlers tend to be "risky" // - secondary SIGSEGV, SIGILL, SIGBUS' may and do happen. // On AIX, PASE there was a case where a SIGSEGV happened, followed @@ -2861,13 +2876,9 @@ OSReturn os::set_native_priority(Thread* thread, int newpri) { param.sched_priority = newpri; int ret = pthread_setschedparam(thr, policy, ¶m); - if (Verbose) { - if (ret == 0) { - fprintf(stderr, "changed priority of thread %d to %d\n", (int)thr, newpri); - } else { - fprintf(stderr, "Could not changed priority for thread %d to %d (error %d, %s)\n", - (int)thr, newpri, ret, strerror(ret)); - } + if (ret != 0) { + trcVerbose("Could not change priority for thread %d to %d (error %d, %s)", + (int)thr, newpri, ret, strerror(ret)); } return (ret == 0) ? OS_OK : OS_ERR; } @@ -2988,7 +2999,6 @@ static void SR_handler(int sig, siginfo_t* siginfo, ucontext_t* context) { errno = old_errno; } - static int SR_initialize() { struct sigaction act; char *s; @@ -3187,7 +3197,6 @@ void javaSignalHandler(int sig, siginfo_t* info, void* uc) { JVM_handle_aix_signal(sig, info, uc, true); } - // This boolean allows users to forward their own non-matching signals // to JVM_handle_aix_signal, harmlessly. bool os::Aix::signal_handlers_are_installed = false; @@ -3381,7 +3390,7 @@ void os::Aix::install_signal_handlers() { set_signal_handler(SIGDANGER, true); if (libjsig_is_loaded) { - // Tell libjsig jvm finishes setting signal handlers + // Tell libjsig jvm finishes setting signal handlers. (*end_signal_setting)(); } @@ -3397,7 +3406,7 @@ void os::Aix::install_signal_handlers() { tty->print_cr("Info: AllowUserSignalHandlers is activated, all active signal checking is disabled"); check_signals = false; } - // need to initialize check_signal_done + // Need to initialize check_signal_done. ::sigemptyset(&check_signal_done); } } @@ -3471,7 +3480,6 @@ static void print_signal_handler(outputStream* st, int sig, st->cr(); } - #define DO_SIGNAL_CHECK(sig) \ if (!sigismember(&check_signal_done, sig)) \ os::Aix::check_signal_handler(sig) @@ -3532,7 +3540,6 @@ void os::Aix::check_signal_handler(int sig) { ? CAST_FROM_FN_PTR(address, act.sa_sigaction) : CAST_FROM_FN_PTR(address, act.sa_handler); - switch(sig) { case SIGSEGV: case SIGBUS: @@ -3685,15 +3692,13 @@ void os::init(void) { pthread_mutex_init(&dl_mutex, NULL); } -// this is called _after_ the global arguments have been parsed +// This is called _after_ the global arguments have been parsed. jint os::init_2(void) { - if (Verbose) { - fprintf(stderr, "processor count: %d\n", os::_processor_count); - fprintf(stderr, "physical memory: %lu\n", Aix::_physical_memory); - } + trcVerbose("processor count: %d", os::_processor_count); + trcVerbose("physical memory: %lu", Aix::_physical_memory); - // initially build up the loaded dll map + // Initially build up the loaded dll map. LoadedLibraries::reload(); const int page_size = Aix::page_size(); @@ -3743,7 +3748,7 @@ jint os::init_2(void) { } if (map_address != (address) MAP_FAILED) { - // map succeeded, but polling_page is not at wished address, unmap and continue. + // Map succeeded, but polling_page is not at wished address, unmap and continue. ::munmap(map_address, map_size); map_address = (address) MAP_FAILED; } @@ -3797,7 +3802,7 @@ jint os::init_2(void) { // Make the stack size a multiple of the page size so that // the yellow/red zones can be guarded. - // note that this can be 0, if no default stacksize was set + // Note that this can be 0, if no default stacksize was set. JavaThread::set_stack_size_at_create(round_to(threadStackSizeInBytes, vm_page_size())); Aix::libpthread_init(); @@ -4088,7 +4093,6 @@ int os::open(const char *path, int oflag, int mode) { return fd; } - // create binary file, rewriting existing file if required int os::create_binary_file(const char* path, bool rewrite_existing) { int oflags = O_WRONLY | O_CREAT; @@ -4169,7 +4173,6 @@ char* os::pd_map_memory(int fd, const char* file_name, size_t file_offset, return mapped_address; } - // Remap a block of memory. char* os::pd_remap_memory(int fd, const char* file_name, size_t file_offset, char *addr, size_t bytes, bool read_only, @@ -4217,14 +4220,14 @@ static bool thread_cpu_time_unchecked(Thread* thread, jlong* p_sys_time, jlong* jlong sys_time = 0; jlong user_time = 0; - // reimplemented using getthrds64(). + // Reimplemented using getthrds64(). // - // goes like this: + // Works like this: // For the thread in question, get the kernel thread id. Then get the // kernel thread statistics using that id. // // This only works of course when no pthread scheduling is used, - // ie there is a 1:1 relationship to kernel threads. + // i.e. there is a 1:1 relationship to kernel threads. // On AIX, see AIXTHREAD_SCOPE variable. pthread_t pthtid = thread->osthread()->pthread_id(); @@ -4371,14 +4374,12 @@ void os::Aix::initialize_os_info() { memset(&uts, 0, sizeof(uts)); strcpy(uts.sysname, "?"); if (::uname(&uts) == -1) { - fprintf(stderr, "uname failed (%d)\n", errno); + trc("uname failed (%d)", errno); guarantee(0, "Could not determine whether we run on AIX or PASE"); } else { - if (Verbose) { - fprintf(stderr,"uname says: sysname \"%s\" version \"%s\" release \"%s\" " - "node \"%s\" machine \"%s\"\n", - uts.sysname, uts.version, uts.release, uts.nodename, uts.machine); - } + trcVerbose("uname says: sysname \"%s\" version \"%s\" release \"%s\" " + "node \"%s\" machine \"%s\"\n", + uts.sysname, uts.version, uts.release, uts.nodename, uts.machine); const int major = atoi(uts.version); assert(major > 0, "invalid OS version"); const int minor = atoi(uts.release); @@ -4390,12 +4391,10 @@ void os::Aix::initialize_os_info() { // We run on AIX. We do not support versions older than AIX 5.3. _on_pase = 0; if (_os_version < 0x0503) { - fprintf(stderr, "AIX release older than AIX 5.3 not supported.\n"); + trc("AIX release older than AIX 5.3 not supported."); assert(false, "AIX release too old."); } else { - if (Verbose) { - fprintf(stderr, "We run on AIX %d.%d\n", major, minor); - } + trcVerbose("We run on AIX %d.%d\n", major, minor); } } else { assert(false, "unknown OS"); @@ -4403,7 +4402,6 @@ void os::Aix::initialize_os_info() { } guarantee(_on_pase != -1 && _os_version, "Could not determine AIX/OS400 release"); - } // end: os::Aix::initialize_os_info() // Scan environment for important settings which might effect the VM. @@ -4441,12 +4439,10 @@ void os::Aix::scan_environment() { // Note: Setting XPG_SUS_ENV in the process is too late. Must be set earlier (before // exec() ? before loading the libjvm ? ....) p = ::getenv("XPG_SUS_ENV"); - if (Verbose) { - fprintf(stderr, "XPG_SUS_ENV=%s.\n", p ? p : ""); - } + trcVerbose("XPG_SUS_ENV=%s.", p ? p : ""); if (p && strcmp(p, "ON") == 0) { _xpg_sus_mode = 1; - fprintf(stderr, "Unsupported setting: XPG_SUS_ENV=ON\n"); + trc("Unsupported setting: XPG_SUS_ENV=ON"); // This is not supported. Worst of all, it changes behaviour of mmap MAP_FIXED to // clobber address ranges. If we ever want to support that, we have to do some // testing first. @@ -4458,10 +4454,7 @@ void os::Aix::scan_environment() { // Switch off AIX internal (pthread) guard pages. This has // immediate effect for any pthread_create calls which follow. p = ::getenv("AIXTHREAD_GUARDPAGES"); - if (Verbose) { - fprintf(stderr, "AIXTHREAD_GUARDPAGES=%s.\n", p ? p : ""); - fprintf(stderr, "setting AIXTHREAD_GUARDPAGES=0.\n"); - } + trcVerbose("AIXTHREAD_GUARDPAGES=%s.", p ? p : ""); rc = ::putenv("AIXTHREAD_GUARDPAGES=0"); guarantee(rc == 0, ""); @@ -4479,7 +4472,7 @@ void os::Aix::initialize_libperfstat() { assert(os::Aix::on_aix(), "AIX only"); if (!libperfstat::init()) { - fprintf(stderr, "libperfstat initialization failed.\n"); + trc("libperfstat initialization failed."); assert(false, "libperfstat initialization failed"); } else { if (Verbose) { @@ -4651,7 +4644,6 @@ static struct timespec* compute_abstime(timespec* abstime, jlong millis) { return abstime; } - // Test-and-clear _Event, always leaves _Event set to 0, returns immediately. // Conceptually TryPark() should be equivalent to park(0). @@ -4732,7 +4724,7 @@ int os::PlatformEvent::park(jlong millis) { while (_Event < 0) { status = pthread_cond_timedwait(_cond, _mutex, &abst); assert_status(status == 0 || status == ETIMEDOUT, - status, "cond_timedwait"); + status, "cond_timedwait"); if (!FilterSpuriousWakeups) break; // previous semantics if (status == ETIMEDOUT) break; // We consume and ignore EINTR and spurious wakeups. @@ -4866,9 +4858,9 @@ void Parker::park(bool isAbsolute, jlong time) { // Optional fast-path check: // Return immediately if a permit is available. if (_counter > 0) { - _counter = 0; - OrderAccess::fence(); - return; + _counter = 0; + OrderAccess::fence(); + return; } Thread* thread = Thread::current(); @@ -4890,7 +4882,6 @@ void Parker::park(bool isAbsolute, jlong time) { unpackTime(&absTime, isAbsolute, time); } - // Enter safepoint region // Beware of deadlocks such as 6317397. // The per-thread Parker:: mutex is a classic leaf-lock. @@ -4978,7 +4969,6 @@ void Parker::unpark() { } } - extern char** environ; // Run the specified command in a separate process. Return its exit value, @@ -4997,44 +4987,43 @@ int os::fork_and_exec(char* cmd) { } else if (pid == 0) { // child process - // try to be consistent with system(), which uses "/usr/bin/sh" on AIX + // Try to be consistent with system(), which uses "/usr/bin/sh" on AIX. execve("/usr/bin/sh", argv, environ); // execve failed _exit(-1); - } else { + } else { // copied from J2SE ..._waitForProcessExit() in UNIXProcess_md.c; we don't // care about the actual exit code, for now. int status; - // Wait for the child process to exit. This returns immediately if + // Wait for the child process to exit. This returns immediately if // the child has already exited. */ while (waitpid(pid, &status, 0) < 0) { - switch (errno) { + switch (errno) { case ECHILD: return 0; case EINTR: break; default: return -1; - } + } } if (WIFEXITED(status)) { - // The child exited normally; get its exit code. - return WEXITSTATUS(status); + // The child exited normally; get its exit code. + return WEXITSTATUS(status); } else if (WIFSIGNALED(status)) { - // The child exited because of a signal - // The best value to return is 0x80 + signal number, - // because that is what all Unix shells do, and because - // it allows callers to distinguish between process exit and - // process death by signal. - return 0x80 + WTERMSIG(status); + // The child exited because of a signal. + // The best value to return is 0x80 + signal number, + // because that is what all Unix shells do, and because + // it allows callers to distinguish between process exit and + // process death by signal. + return 0x80 + WTERMSIG(status); } else { - // Unknown exit code; pass it through - return status; + // Unknown exit code; pass it through. + return status; } } - // Remove warning. return -1; } @@ -5049,7 +5038,7 @@ bool os::is_headless_jre() { struct stat statbuf; char buf[MAXPATHLEN]; char libmawtpath[MAXPATHLEN]; - const char *xawtstr = "/xawt/libmawt.so"; + const char *xawtstr = "/xawt/libmawt.so"; const char *new_xawtstr = "/libawt_xawt.so"; char *p; @@ -5090,6 +5079,9 @@ int os::get_core_path(char* buffer, size_t bufferSize) { return 0; } + jio_snprintf(buffer, bufferSize, "%s/core or core.%d", + p, current_process_id()); + return strlen(buffer); } diff --git a/hotspot/src/os/aix/vm/os_aix.hpp b/hotspot/src/os/aix/vm/os_aix.hpp index a7d2717c8e0..01831fb7cbc 100644 --- a/hotspot/src/os/aix/vm/os_aix.hpp +++ b/hotspot/src/os/aix/vm/os_aix.hpp @@ -209,7 +209,7 @@ class Aix { return _can_use_16M_pages == 1 ? true : false; } - static address ucontext_get_pc(ucontext_t* uc); + static address ucontext_get_pc(const ucontext_t* uc); static intptr_t* ucontext_get_sp(ucontext_t* uc); static intptr_t* ucontext_get_fp(ucontext_t* uc); // Set PC into context. Needed for continuation after signal. diff --git a/hotspot/src/os/bsd/vm/osThread_bsd.cpp b/hotspot/src/os/bsd/vm/osThread_bsd.cpp index 92c6d0c4dac..de1383be848 100644 --- a/hotspot/src/os/bsd/vm/osThread_bsd.cpp +++ b/hotspot/src/os/bsd/vm/osThread_bsd.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 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 @@ -43,7 +43,8 @@ void OSThread::pd_initialize() { sigemptyset(&_caller_sigmask); - _startThread_lock = new Monitor(Mutex::event, "startThread_lock", true); + _startThread_lock = new Monitor(Mutex::event, "startThread_lock", true, + Monitor::_safepoint_check_never); assert(_startThread_lock !=NULL, "check"); } diff --git a/hotspot/src/os/bsd/vm/os_bsd.cpp b/hotspot/src/os/bsd/vm/os_bsd.cpp index 1d62a712a06..cddb9449712 100644 --- a/hotspot/src/os/bsd/vm/os_bsd.cpp +++ b/hotspot/src/os/bsd/vm/os_bsd.cpp @@ -4673,7 +4673,7 @@ bool os::is_headless_jre() { // Get the default path to the core file // Returns the length of the string int os::get_core_path(char* buffer, size_t bufferSize) { - int n = jio_snprintf(buffer, bufferSize, "/cores"); + int n = jio_snprintf(buffer, bufferSize, "/cores/core.%d", current_process_id()); // Truncate if theoretical string was longer than bufferSize n = MIN2(n, (int)bufferSize); diff --git a/hotspot/src/os/linux/vm/osThread_linux.cpp b/hotspot/src/os/linux/vm/osThread_linux.cpp index 8d27b5651bc..381e7b0e7ba 100644 --- a/hotspot/src/os/linux/vm/osThread_linux.cpp +++ b/hotspot/src/os/linux/vm/osThread_linux.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 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 @@ -39,7 +39,8 @@ void OSThread::pd_initialize() { sigemptyset(&_caller_sigmask); - _startThread_lock = new Monitor(Mutex::event, "startThread_lock", true); + _startThread_lock = new Monitor(Mutex::event, "startThread_lock", true, + Monitor::_safepoint_check_never); assert(_startThread_lock !=NULL, "check"); } diff --git a/hotspot/src/os/linux/vm/os_linux.cpp b/hotspot/src/os/linux/vm/os_linux.cpp index 85ec17dcc40..4ad556ad388 100644 --- a/hotspot/src/os/linux/vm/os_linux.cpp +++ b/hotspot/src/os/linux/vm/os_linux.cpp @@ -5988,13 +5988,70 @@ bool os::is_headless_jre() { // Get the default path to the core file // Returns the length of the string int os::get_core_path(char* buffer, size_t bufferSize) { - const char* p = get_current_directory(buffer, bufferSize); + /* + * Max length of /proc/sys/kernel/core_pattern is 128 characters. + * See https://www.kernel.org/doc/Documentation/sysctl/kernel.txt + */ + const int core_pattern_len = 129; + char core_pattern[core_pattern_len] = {0}; - if (p == NULL) { - assert(p != NULL, "failed to get current directory"); + int core_pattern_file = ::open("/proc/sys/kernel/core_pattern", O_RDONLY); + if (core_pattern_file != -1) { + ssize_t ret = ::read(core_pattern_file, core_pattern, core_pattern_len); + ::close(core_pattern_file); + + if (ret > 0) { + char *last_char = core_pattern + strlen(core_pattern) - 1; + + if (*last_char == '\n') { + *last_char = '\0'; + } + } + } + + if (strlen(core_pattern) == 0) { return 0; } + char *pid_pos = strstr(core_pattern, "%p"); + size_t written; + + if (core_pattern[0] == '/') { + written = jio_snprintf(buffer, bufferSize, core_pattern); + } else { + char cwd[PATH_MAX]; + + const char* p = get_current_directory(cwd, PATH_MAX); + if (p == NULL) { + assert(p != NULL, "failed to get current directory"); + return 0; + } + + if (core_pattern[0] == '|') { + written = jio_snprintf(buffer, bufferSize, + "\"%s\" (or dumping to %s/core.%d)", + &core_pattern[1], p, current_process_id()); + } else { + written = jio_snprintf(buffer, bufferSize, "%s/%s", p, core_pattern); + } + } + + if ((written >= 0) && (written < bufferSize) + && (pid_pos == NULL) && (core_pattern[0] != '|')) { + int core_uses_pid_file = ::open("/proc/sys/kernel/core_uses_pid", O_RDONLY); + + if (core_uses_pid_file != -1) { + char core_uses_pid = 0; + ssize_t ret = ::read(core_uses_pid_file, &core_uses_pid, 1); + ::close(core_uses_pid_file); + + if (core_uses_pid == '1'){ + jio_snprintf(buffer + written, bufferSize - written, + ".%d", current_process_id()); + } + } + } + return strlen(buffer); } diff --git a/hotspot/src/os/posix/vm/os_posix.cpp b/hotspot/src/os/posix/vm/os_posix.cpp index beb8754198f..d64aa0ae156 100644 --- a/hotspot/src/os/posix/vm/os_posix.cpp +++ b/hotspot/src/os/posix/vm/os_posix.cpp @@ -51,15 +51,24 @@ void os::check_or_create_dump(void* exceptionRecord, void* contextRecord, char* struct rlimit rlim; bool success; - n = get_core_path(buffer, bufferSize); + char core_path[PATH_MAX]; + n = get_core_path(core_path, PATH_MAX); - if (getrlimit(RLIMIT_CORE, &rlim) != 0) { - jio_snprintf(buffer + n, bufferSize - n, "/core or core.%d (may not exist)", current_process_id()); + if (n <= 0) { + jio_snprintf(buffer, bufferSize, "core.%d (may not exist)", current_process_id()); + success = true; +#ifdef LINUX + } else if (core_path[0] == '"') { // redirect to user process + jio_snprintf(buffer, bufferSize, "Core dumps may be processed with %s", core_path); + success = true; +#endif + } else if (getrlimit(RLIMIT_CORE, &rlim) != 0) { + jio_snprintf(buffer, bufferSize, "%s (may not exist)", core_path); success = true; } else { switch(rlim.rlim_cur) { case RLIM_INFINITY: - jio_snprintf(buffer + n, bufferSize - n, "/core or core.%d", current_process_id()); + jio_snprintf(buffer, bufferSize, "%s", core_path); success = true; break; case 0: @@ -67,11 +76,12 @@ void os::check_or_create_dump(void* exceptionRecord, void* contextRecord, char* success = false; break; default: - jio_snprintf(buffer + n, bufferSize - n, "/core or core.%d (max size %lu kB). To ensure a full core dump, try \"ulimit -c unlimited\" before starting Java again", current_process_id(), (unsigned long)(rlim.rlim_cur >> 10)); + jio_snprintf(buffer, bufferSize, "%s (max size %lu kB). To ensure a full core dump, try \"ulimit -c unlimited\" before starting Java again", core_path, (unsigned long)(rlim.rlim_cur >> 10)); success = true; break; } } + VMError::report_coredump_status(buffer, success); } @@ -89,8 +99,8 @@ int os::get_native_stack(address* stack, int frames, int toSkip) { } else { stack[frame_idx ++] = fr.pc(); } - if (fr.fp() == NULL || os::is_first_C_frame(&fr) - ||fr.sender_pc() == NULL || fr.cb() != NULL) break; + if (fr.fp() == NULL || fr.cb() != NULL || + fr.sender_pc() == NULL || os::is_first_C_frame(&fr)) break; if (fr.sender_pc() && !os::is_first_C_frame(&fr)) { fr = os::get_sender_for_C_frame(&fr); diff --git a/hotspot/src/os/solaris/vm/os_solaris.cpp b/hotspot/src/os/solaris/vm/os_solaris.cpp index 637bd033913..8a280b0b5ae 100644 --- a/hotspot/src/os/solaris/vm/os_solaris.cpp +++ b/hotspot/src/os/solaris/vm/os_solaris.cpp @@ -5979,6 +5979,9 @@ int os::get_core_path(char* buffer, size_t bufferSize) { return 0; } + jio_snprintf(buffer, bufferSize, "%s/core or core.%d", + p, current_process_id()); + return strlen(buffer); } diff --git a/hotspot/src/os/windows/vm/os_windows.cpp b/hotspot/src/os/windows/vm/os_windows.cpp index 924dd4966e6..fb09815cf79 100644 --- a/hotspot/src/os/windows/vm/os_windows.cpp +++ b/hotspot/src/os/windows/vm/os_windows.cpp @@ -3074,7 +3074,7 @@ char* os::reserve_memory_aligned(size_t size, size_t alignment) { char* os::pd_reserve_memory(size_t bytes, char* addr, size_t alignment_hint) { assert((size_t)addr % os::vm_allocation_granularity() == 0, "reserve alignment"); - assert(bytes % os::vm_allocation_granularity() == 0, "reserve block size"); + assert(bytes % os::vm_page_size() == 0, "reserve page size"); char* res; // note that if UseLargePages is on, all the areas that require interleaving // will go thru reserve_memory_special rather than thru here. @@ -3768,7 +3768,6 @@ HINSTANCE os::win32::load_Windows_dll(const char* name, char *ebuf, return NULL; } -#define MAX_EXIT_HANDLES PRODUCT_ONLY(32) NOT_PRODUCT(128) #define EXIT_TIMEOUT PRODUCT_ONLY(1000) NOT_PRODUCT(4000) /* 1 sec in product, 4 sec in debug */ static BOOL CALLBACK init_crit_sect_call(PINIT_ONCE, PVOID pcrit_sect, PVOID*) { @@ -3787,7 +3786,7 @@ int os::win32::exit_process_or_thread(Ept what, int exit_code) { // _endthreadex(). // Should be large enough to avoid blocking the exiting thread due to lack of // a free slot. - static HANDLE handles[MAX_EXIT_HANDLES]; + static HANDLE handles[MAXIMUM_WAIT_OBJECTS]; static int handle_count = 0; static INIT_ONCE init_once_crit_sect = INIT_ONCE_STATIC_INIT; @@ -3809,32 +3808,34 @@ int os::win32::exit_process_or_thread(Ept what, int exit_code) { if (res == WAIT_TIMEOUT) { handles[j++] = handles[i]; } else { - if (res != WAIT_OBJECT_0) { - warning("WaitForSingleObject failed in %s: %d\n", __FILE__, __LINE__); - // Don't keep the handle, if we failed waiting for it. + if (res == WAIT_FAILED) { + warning("WaitForSingleObject failed (%u) in %s: %d\n", + GetLastError(), __FILE__, __LINE__); } + // Don't keep the handle, if we failed waiting for it. CloseHandle(handles[i]); } } // If there's no free slot in the array of the kept handles, we'll have to // wait until at least one thread completes exiting. - if ((handle_count = j) == MAX_EXIT_HANDLES) { + if ((handle_count = j) == MAXIMUM_WAIT_OBJECTS) { // Raise the priority of the oldest exiting thread to increase its chances // to complete sooner. SetThreadPriority(handles[0], THREAD_PRIORITY_ABOVE_NORMAL); - res = WaitForMultipleObjects(MAX_EXIT_HANDLES, handles, FALSE, EXIT_TIMEOUT); - if (res >= WAIT_OBJECT_0 && res < (WAIT_OBJECT_0 + MAX_EXIT_HANDLES)) { + res = WaitForMultipleObjects(MAXIMUM_WAIT_OBJECTS, handles, FALSE, EXIT_TIMEOUT); + if (res >= WAIT_OBJECT_0 && res < (WAIT_OBJECT_0 + MAXIMUM_WAIT_OBJECTS)) { i = (res - WAIT_OBJECT_0); - handle_count = MAX_EXIT_HANDLES - 1; + handle_count = MAXIMUM_WAIT_OBJECTS - 1; for (; i < handle_count; ++i) { handles[i] = handles[i + 1]; } } else { - warning("WaitForMultipleObjects %s in %s: %d\n", - (res == WAIT_FAILED ? "failed" : "timed out"), __FILE__, __LINE__); + warning("WaitForMultipleObjects %s (%u) in %s: %d\n", + (res == WAIT_FAILED ? "failed" : "timed out"), + GetLastError(), __FILE__, __LINE__); // Don't keep handles, if we failed waiting for them. - for (i = 0; i < MAX_EXIT_HANDLES; ++i) { + for (i = 0; i < MAXIMUM_WAIT_OBJECTS; ++i) { CloseHandle(handles[i]); } handle_count = 0; @@ -3846,7 +3847,8 @@ int os::win32::exit_process_or_thread(Ept what, int exit_code) { hthr = GetCurrentThread(); if (!DuplicateHandle(hproc, hthr, hproc, &handles[handle_count], 0, FALSE, DUPLICATE_SAME_ACCESS)) { - warning("DuplicateHandle failed in %s: %d\n", __FILE__, __LINE__); + warning("DuplicateHandle failed (%u) in %s: %d\n", + GetLastError(), __FILE__, __LINE__); } else { ++handle_count; } @@ -3869,9 +3871,10 @@ int os::win32::exit_process_or_thread(Ept what, int exit_code) { SetThreadPriority(handles[i], THREAD_PRIORITY_ABOVE_NORMAL); } res = WaitForMultipleObjects(handle_count, handles, TRUE, EXIT_TIMEOUT); - if (res < WAIT_OBJECT_0 || res >= (WAIT_OBJECT_0 + MAX_EXIT_HANDLES)) { - warning("WaitForMultipleObjects %s in %s: %d\n", - (res == WAIT_FAILED ? "failed" : "timed out"), __FILE__, __LINE__); + if (res == WAIT_FAILED || res == WAIT_TIMEOUT) { + warning("WaitForMultipleObjects %s (%u) in %s: %d\n", + (res == WAIT_FAILED ? "failed" : "timed out"), + GetLastError(), __FILE__, __LINE__); } for (i = 0; i < handle_count; ++i) { CloseHandle(handles[i]); @@ -3909,7 +3912,6 @@ int os::win32::exit_process_or_thread(Ept what, int exit_code) { return exit_code; } -#undef MAX_EXIT_HANDLES #undef EXIT_TIMEOUT void os::win32::setmode_streams() { diff --git a/hotspot/src/os_cpu/aix_ppc/vm/os_aix_ppc.cpp b/hotspot/src/os_cpu/aix_ppc/vm/os_aix_ppc.cpp index da8f4448d46..53f13f07826 100644 --- a/hotspot/src/os_cpu/aix_ppc/vm/os_aix_ppc.cpp +++ b/hotspot/src/os_cpu/aix_ppc/vm/os_aix_ppc.cpp @@ -91,8 +91,9 @@ void os::initialize_thread(Thread *thread) { } // Frame information (pc, sp, fp) retrieved via ucontext // always looks like a C-frame according to the frame -// conventions in frame_ppc64.hpp. -address os::Aix::ucontext_get_pc(ucontext_t * uc) { +// conventions in frame_ppc.hpp. + +address os::Aix::ucontext_get_pc(const ucontext_t * uc) { return (address)uc->uc_mcontext.jmp_context.iar; } @@ -486,7 +487,7 @@ void os::Aix::init_thread_fpu_state(void) { //////////////////////////////////////////////////////////////////////////////// // thread stack -size_t os::Aix::min_stack_allowed = 768*K; +size_t os::Aix::min_stack_allowed = 128*K; // Aix is always in floating stack mode. The stack size for a new // thread can be set via pthread_attr_setstacksize(). @@ -499,7 +500,7 @@ size_t os::Aix::default_stack_size(os::ThreadType thr_type) { // because of the strange 'fallback logic' in os::create_thread(). // Better set CompilerThreadStackSize in globals_.hpp if you want to // specify a different stack size for compiler threads! - size_t s = (thr_type == os::compiler_thread ? 4 * M : 1024 * K); + size_t s = (thr_type == os::compiler_thread ? 4 * M : 1 * M); return s; } diff --git a/hotspot/src/os_cpu/aix_ppc/vm/os_aix_ppc.hpp b/hotspot/src/os_cpu/aix_ppc/vm/os_aix_ppc.hpp index 4f307279399..44fa7db3838 100644 --- a/hotspot/src/os_cpu/aix_ppc/vm/os_aix_ppc.hpp +++ b/hotspot/src/os_cpu/aix_ppc/vm/os_aix_ppc.hpp @@ -23,8 +23,8 @@ * */ -#ifndef OS_CPU_AIX_OJDKPPC_VM_OS_AIX_PPC_HPP -#define OS_CPU_AIX_OJDKPPC_VM_OS_AIX_PPC_HPP +#ifndef OS_CPU_AIX_PPC_VM_OS_AIX_PPC_HPP +#define OS_CPU_AIX_PPC_VM_OS_AIX_PPC_HPP static void setup_fpu() {} @@ -32,4 +32,4 @@ // Note: Currently only used in 64 bit Windows implementations static bool register_code_area(char *low, char *high) { return true; } -#endif // OS_CPU_AIX_OJDKPPC_VM_OS_AIX_PPC_HPP +#endif // OS_CPU_AIX_PPC_VM_OS_AIX_PPC_HPP diff --git a/hotspot/src/os_cpu/aix_ppc/vm/prefetch_aix_ppc.inline.hpp b/hotspot/src/os_cpu/aix_ppc/vm/prefetch_aix_ppc.inline.hpp index 3d855f7d0d3..85c62b6640f 100644 --- a/hotspot/src/os_cpu/aix_ppc/vm/prefetch_aix_ppc.inline.hpp +++ b/hotspot/src/os_cpu/aix_ppc/vm/prefetch_aix_ppc.inline.hpp @@ -23,8 +23,8 @@ * */ -#ifndef OS_CPU_AIX_PPC_64_VM_PREFETCH_AIX_PPC_64_INLINE_HPP -#define OS_CPU_AIX_PPC_64_VM_PREFETCH_AIX_PPC_64_INLINE_HPP +#ifndef OS_CPU_AIX_PPC_VM_PREFETCH_AIX_PPC_INLINE_HPP +#define OS_CPU_AIX_PPC_VM_PREFETCH_AIX_PPC_INLINE_HPP #include "runtime/prefetch.hpp" @@ -55,4 +55,4 @@ inline void Prefetch::write(void *loc, intx interval) { #endif } -#endif // OS_CPU_AIX_PPC_64_VM_PREFETCH_AIX_PPC_64_INLINE_HPP +#endif // OS_CPU_AIX_PPC_VM_PREFETCH_AIX_PPC_INLINE_HPP diff --git a/hotspot/src/os_cpu/aix_ppc/vm/threadLS_aix_ppc.hpp b/hotspot/src/os_cpu/aix_ppc/vm/threadLS_aix_ppc.hpp index 1aacc8f456a..825b0b8435a 100644 --- a/hotspot/src/os_cpu/aix_ppc/vm/threadLS_aix_ppc.hpp +++ b/hotspot/src/os_cpu/aix_ppc/vm/threadLS_aix_ppc.hpp @@ -23,8 +23,8 @@ * */ -#ifndef OS_CPU_AIX_OJDKPPC_VM_THREADLS_AIX_PPC_HPP -#define OS_CPU_AIX_OJDKPPC_VM_THREADLS_AIX_PPC_HPP +#ifndef OS_CPU_AIX_PPC_VM_THREADLS_AIX_PPC_HPP +#define OS_CPU_AIX_PPC_VM_THREADLS_AIX_PPC_HPP // Processor dependent parts of ThreadLocalStorage @@ -33,4 +33,4 @@ public: return (Thread *) os::thread_local_storage_at(thread_index()); } -#endif // OS_CPU_AIX_OJDKPPC_VM_THREADLS_AIX_PPC_HPP +#endif // OS_CPU_AIX_PPC_VM_THREADLS_AIX_PPC_HPP diff --git a/hotspot/src/os_cpu/aix_ppc/vm/thread_aix_ppc.hpp b/hotspot/src/os_cpu/aix_ppc/vm/thread_aix_ppc.hpp index c74b43e16b7..2ca7c861cc9 100644 --- a/hotspot/src/os_cpu/aix_ppc/vm/thread_aix_ppc.hpp +++ b/hotspot/src/os_cpu/aix_ppc/vm/thread_aix_ppc.hpp @@ -23,8 +23,8 @@ * */ -#ifndef OS_CPU_AIX_OJDKPPC_VM_THREAD_AIX_PPC_HPP -#define OS_CPU_AIX_OJDKPPC_VM_THREAD_AIX_PPC_HPP +#ifndef OS_CPU_AIX_PPC_VM_THREAD_AIX_PPC_HPP +#define OS_CPU_AIX_PPC_VM_THREAD_AIX_PPC_HPP private: void pd_initialize() { @@ -76,4 +76,4 @@ intptr_t* last_interpreter_fp() { return _last_interpreter_fp; } -#endif // OS_CPU_AIX_OJDKPPC_VM_THREAD_AIX_PPC_HPP +#endif // OS_CPU_AIX_PPC_VM_THREAD_AIX_PPC_HPP diff --git a/hotspot/src/os_cpu/linux_ppc/vm/os_linux_ppc.cpp b/hotspot/src/os_cpu/linux_ppc/vm/os_linux_ppc.cpp index 6a243c2a1ac..990ca3b1fa5 100644 --- a/hotspot/src/os_cpu/linux_ppc/vm/os_linux_ppc.cpp +++ b/hotspot/src/os_cpu/linux_ppc/vm/os_linux_ppc.cpp @@ -453,7 +453,7 @@ void os::Linux::set_fpu_control_word(int fpu_control) { //////////////////////////////////////////////////////////////////////////////// // thread stack -size_t os::Linux::min_stack_allowed = 768*K; +size_t os::Linux::min_stack_allowed = 128*K; bool os::Linux::supports_variable_stack_size() { return true; } diff --git a/hotspot/src/share/vm/classfile/classFileParser.cpp b/hotspot/src/share/vm/classfile/classFileParser.cpp index 7d54c6e2ed6..f80d0fcc00e 100644 --- a/hotspot/src/share/vm/classfile/classFileParser.cpp +++ b/hotspot/src/share/vm/classfile/classFileParser.cpp @@ -3108,21 +3108,39 @@ void ClassFileParser::apply_parsed_class_attributes(instanceKlassHandle k) { } } -// Transfer ownership of metadata allocated to the InstanceKlass. -void ClassFileParser::apply_parsed_class_metadata( - instanceKlassHandle this_klass, - int java_fields_count, TRAPS) { - // Assign annotations if needed - if (_annotations != NULL || _type_annotations != NULL || - _fields_annotations != NULL || _fields_type_annotations != NULL) { +// Create the Annotations object that will +// hold the annotations array for the Klass. +void ClassFileParser::create_combined_annotations(TRAPS) { + if (_annotations == NULL && + _type_annotations == NULL && + _fields_annotations == NULL && + _fields_type_annotations == NULL) { + // Don't create the Annotations object unnecessarily. + return; + } + Annotations* annotations = Annotations::allocate(_loader_data, CHECK); annotations->set_class_annotations(_annotations); annotations->set_class_type_annotations(_type_annotations); annotations->set_fields_annotations(_fields_annotations); annotations->set_fields_type_annotations(_fields_type_annotations); - this_klass->set_annotations(annotations); - } + // This is the Annotations object that will be + // assigned to InstanceKlass being constructed. + _combined_annotations = annotations; + + // The annotations arrays below has been transfered the + // _combined_annotations so these fields can now be cleared. + _annotations = NULL; + _type_annotations = NULL; + _fields_annotations = NULL; + _fields_type_annotations = NULL; +} + +// Transfer ownership of metadata allocated to the InstanceKlass. +void ClassFileParser::apply_parsed_class_metadata( + instanceKlassHandle this_klass, + int java_fields_count, TRAPS) { _cp->set_pool_holder(this_klass()); this_klass->set_constants(_cp); this_klass->set_fields(_fields, java_fields_count); @@ -3130,6 +3148,7 @@ void ClassFileParser::apply_parsed_class_metadata( this_klass->set_inner_classes(_inner_classes); this_klass->set_local_interfaces(_local_interfaces); this_klass->set_transitive_interfaces(_transitive_interfaces); + this_klass->set_annotations(_combined_annotations); // Clear out these fields so they don't get deallocated by the destructor clear_class_metadata(); @@ -4002,6 +4021,10 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name, ClassAnnotationCollector parsed_annotations; parse_classfile_attributes(&parsed_annotations, CHECK_(nullHandle)); + // Finalize the Annotations metadata object, + // now that all annotation arrays have been created. + create_combined_annotations(CHECK_(nullHandle)); + // Make sure this is the end of class file stream guarantee_property(cfs->at_eos(), "Extra bytes at the end of class file %s", CHECK_(nullHandle)); @@ -4302,10 +4325,27 @@ ClassFileParser::~ClassFileParser() { InstanceKlass::deallocate_interfaces(_loader_data, _super_klass(), _local_interfaces, _transitive_interfaces); - MetadataFactory::free_array(_loader_data, _annotations); - MetadataFactory::free_array(_loader_data, _type_annotations); - Annotations::free_contents(_loader_data, _fields_annotations); - Annotations::free_contents(_loader_data, _fields_type_annotations); + if (_combined_annotations != NULL) { + // After all annotations arrays have been created, they are installed into the + // Annotations object that will be assigned to the InstanceKlass being created. + + // Deallocate the Annotations object and the installed annotations arrays. + _combined_annotations->deallocate_contents(_loader_data); + + // If the _combined_annotations pointer is non-NULL, + // then the other annotations fields should have been cleared. + assert(_annotations == NULL, "Should have been cleared"); + assert(_type_annotations == NULL, "Should have been cleared"); + assert(_fields_annotations == NULL, "Should have been cleared"); + assert(_fields_type_annotations == NULL, "Should have been cleared"); + } else { + // If the annotations arrays were not installed into the Annotations object, + // then they have to be deallocated explicitly. + MetadataFactory::free_array(_loader_data, _annotations); + MetadataFactory::free_array(_loader_data, _type_annotations); + Annotations::free_contents(_loader_data, _fields_annotations); + Annotations::free_contents(_loader_data, _fields_type_annotations); + } clear_class_metadata(); diff --git a/hotspot/src/share/vm/classfile/classFileParser.hpp b/hotspot/src/share/vm/classfile/classFileParser.hpp index b2efa8ceba3..c3d23df881c 100644 --- a/hotspot/src/share/vm/classfile/classFileParser.hpp +++ b/hotspot/src/share/vm/classfile/classFileParser.hpp @@ -75,6 +75,7 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC { Array* _inner_classes; Array* _local_interfaces; Array* _transitive_interfaces; + Annotations* _combined_annotations; AnnotationArray* _annotations; AnnotationArray* _type_annotations; Array* _fields_annotations; @@ -86,6 +87,8 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC { void set_class_generic_signature_index(u2 x) { _generic_signature_index = x; } void set_class_sde_buffer(char* x, int len) { _sde_buffer = x; _sde_length = len; } + void create_combined_annotations(TRAPS); + void init_parsed_class_attributes(ClassLoaderData* loader_data) { _loader_data = loader_data; _synthetic_flag = false; @@ -110,6 +113,7 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC { _inner_classes = NULL; _local_interfaces = NULL; _transitive_interfaces = NULL; + _combined_annotations = NULL; _annotations = _type_annotations = NULL; _fields_annotations = _fields_type_annotations = NULL; } diff --git a/hotspot/src/share/vm/classfile/classLoaderData.cpp b/hotspot/src/share/vm/classfile/classLoaderData.cpp index e433f0f6e5c..96e48340847 100644 --- a/hotspot/src/share/vm/classfile/classLoaderData.cpp +++ b/hotspot/src/share/vm/classfile/classLoaderData.cpp @@ -81,7 +81,8 @@ ClassLoaderData::ClassLoaderData(Handle h_class_loader, bool is_anonymous, Depen _metaspace(NULL), _unloading(false), _klasses(NULL), _claimed(0), _jmethod_ids(NULL), _handles(NULL), _deallocate_list(NULL), _next(NULL), _dependencies(dependencies), - _metaspace_lock(new Mutex(Monitor::leaf+1, "Metaspace allocation lock", true)) { + _metaspace_lock(new Mutex(Monitor::leaf+1, "Metaspace allocation lock", true, + Monitor::_safepoint_check_never)) { // empty } diff --git a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp index 1658e6612bd..2264559e3b3 100644 --- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp @@ -83,9 +83,11 @@ CompactibleFreeListSpace::CompactibleFreeListSpace(BlockOffsetSharedArray* bs, // Note: this requires that CFLspace c'tors // are called serially in the order in which the locks are // are acquired in the program text. This is true today. - _freelistLock(_lockRank--, "CompactibleFreeListSpace._lock", true), + _freelistLock(_lockRank--, "CompactibleFreeListSpace._lock", true, + Monitor::_safepoint_check_sometimes), _parDictionaryAllocLock(Mutex::leaf - 1, // == rank(ExpandHeap_lock) - 1 - "CompactibleFreeListSpace._dict_par_lock", true), + "CompactibleFreeListSpace._dict_par_lock", true, + Monitor::_safepoint_check_never), _rescan_task_size(CardTableModRefBS::card_size_in_words * BitsPerWord * CMSRescanMultiple), _marking_task_size(CardTableModRefBS::card_size_in_words * BitsPerWord * @@ -152,8 +154,7 @@ CompactibleFreeListSpace::CompactibleFreeListSpace(BlockOffsetSharedArray* bs, // Initialize locks for parallel case. for (size_t i = IndexSetStart; i < IndexSetSize; i += IndexSetStride) { _indexedFreeListParLocks[i] = new Mutex(Mutex::leaf - 1, // == ExpandHeap_lock - 1 - "a freelist par lock", - true); + "a freelist par lock", true, Mutex::_safepoint_check_sometimes); DEBUG_ONLY( _indexedFreeList[i].set_protecting_lock(_indexedFreeListParLocks[i]); ) @@ -2559,12 +2560,12 @@ void CompactibleFreeListSpace::printFLCensus(size_t sweep_count) const { x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, x, \ x } -// Initialize with default setting of CMSParPromoteBlocksToClaim, _not_ -// OldPLABSize, whose static default is different; if overridden at the +// Initialize with default setting for CMS, _not_ +// generic OldPLABSize, whose static default is different; if overridden at the // command-line, this will get reinitialized via a call to // modify_initialization() below. AdaptiveWeightedAverage CFLS_LAB::_blocks_to_claim[] = - VECTOR_257(AdaptiveWeightedAverage(OldPLABWeight, (float)CMSParPromoteBlocksToClaim)); + VECTOR_257(AdaptiveWeightedAverage(OldPLABWeight, (float)CFLS_LAB::_default_dynamic_old_plab_size)); size_t CFLS_LAB::_global_num_blocks[] = VECTOR_257(0); uint CFLS_LAB::_global_num_workers[] = VECTOR_257(0); diff --git a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp index 11f622b1258..b33bdc71440 100644 --- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp @@ -690,6 +690,9 @@ class CFLS_LAB : public CHeapObj { void get_from_global_pool(size_t word_sz, AdaptiveFreeList* fl); public: + static const int _default_dynamic_old_plab_size = 16; + static const int _default_static_old_plab_size = 50; + CFLS_LAB(CompactibleFreeListSpace* cfls); // Allocate and return a block of the given size, or else return NULL. diff --git a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp index d6d054d184e..8318c3a048e 100644 --- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp @@ -42,6 +42,7 @@ #include "gc_implementation/shared/isGCActiveMark.hpp" #include "gc_interface/collectedHeap.inline.hpp" #include "memory/allocation.hpp" +#include "memory/cardGeneration.inline.hpp" #include "memory/cardTableRS.hpp" #include "memory/collectorPolicy.hpp" #include "memory/gcLocker.inline.hpp" @@ -479,7 +480,9 @@ CMSCollector::CMSCollector(ConcurrentMarkSweepGeneration* cmsGen, _restart_addr(NULL), _overflow_list(NULL), _stats(cmsGen), - _eden_chunk_lock(new Mutex(Mutex::leaf + 1, "CMS_eden_chunk_lock", true)), + _eden_chunk_lock(new Mutex(Mutex::leaf + 1, "CMS_eden_chunk_lock", true, + //verify that this lock should be acquired with safepoint check. + Monitor::_safepoint_check_sometimes)), _eden_chunk_array(NULL), // may be set in ctor body _eden_chunk_capacity(0), // -- ditto -- _eden_chunk_index(0), // -- ditto -- @@ -793,11 +796,6 @@ void ConcurrentMarkSweepGeneration::promotion_failure_occurred() { } } -CompactibleSpace* -ConcurrentMarkSweepGeneration::first_compaction_space() const { - return _cmsSpace; -} - void ConcurrentMarkSweepGeneration::reset_after_compaction() { // Clear the promotion information. These pointers can be adjusted // along with all the other pointers into the heap but @@ -808,10 +806,6 @@ void ConcurrentMarkSweepGeneration::reset_after_compaction() { } } -void ConcurrentMarkSweepGeneration::space_iterate(SpaceClosure* blk, bool usedOnly) { - blk->do_space(_cmsSpace); -} - void ConcurrentMarkSweepGeneration::compute_new_size() { assert_locked_or_safepoint(Heap_lock); @@ -882,7 +876,7 @@ void ConcurrentMarkSweepGeneration::compute_new_size_free_list() { expand_bytes); } // safe if expansion fails - expand(expand_bytes, 0, CMSExpansionCause::_satisfy_free_ratio); + expand_for_gc_cause(expand_bytes, 0, CMSExpansionCause::_satisfy_free_ratio); if (PrintGCDetails && Verbose) { gclog_or_tty->print_cr(" Expanded free fraction %f", ((double) free()) / capacity()); @@ -1048,8 +1042,7 @@ oop ConcurrentMarkSweepGeneration::promote(oop obj, size_t obj_size) { if (res == NULL) { // expand and retry size_t s = _cmsSpace->expansionSpaceRequired(obj_size); // HeapWords - expand(s*HeapWordSize, MinHeapDeltaBytes, - CMSExpansionCause::_satisfy_promotion); + expand_for_gc_cause(s*HeapWordSize, MinHeapDeltaBytes, CMSExpansionCause::_satisfy_promotion); // Since there's currently no next generation, we don't try to promote // into a more senior generation. assert(next_gen() == NULL, "assumption, based upon which no attempt " @@ -1618,14 +1611,15 @@ void CMSCollector::acquire_control_and_collect(bool full, // If the collection is being acquired from the background // collector, there may be references on the discovered - // references lists that have NULL referents (being those - // that were concurrently cleared by a mutator) or - // that are no longer active (having been enqueued concurrently - // by the mutator). - // Scrub the list of those references because Mark-Sweep-Compact - // code assumes referents are not NULL and that all discovered - // Reference objects are active. - ref_processor()->clean_up_discovered_references(); + // references lists. Abandon those references, since some + // of them may have become unreachable after concurrent + // discovery; the STW compacting collector will redo discovery + // more precisely, without being subject to floating garbage. + // Leaving otherwise unreachable references in the discovered + // lists would require special handling. + ref_processor()->disable_discovery(); + ref_processor()->abandon_partial_discovery(); + ref_processor()->verify_no_references_recorded(); if (first_state > Idling) { save_heap_summary(); @@ -1691,7 +1685,7 @@ void CMSCollector::do_compaction_work(bool clear_all_soft_refs) { ReferenceProcessorMTDiscoveryMutator rp_mut_discovery(ref_processor(), false); ref_processor()->set_enqueuing_is_done(false); - ref_processor()->enable_discovery(false /*verify_disabled*/, false /*check_no_refs*/); + ref_processor()->enable_discovery(); ref_processor()->setup_policy(clear_all_soft_refs); // If an asynchronous collection finishes, the _modUnionTable is // all clear. If we are assuming the collection from an asynchronous @@ -2624,13 +2618,6 @@ oop_since_save_marks_iterate##nv_suffix(OopClosureType* cl) { \ ALL_SINCE_SAVE_MARKS_CLOSURES(CMS_SINCE_SAVE_MARKS_DEFN) -void -ConcurrentMarkSweepGeneration::younger_refs_iterate(OopsInGenClosure* cl) { - cl->set_generation(this); - younger_refs_in_space_iterate(_cmsSpace, cl); - cl->reset_generation(); -} - void ConcurrentMarkSweepGeneration::oop_iterate(ExtendedOopClosure* cl) { if (freelistLock()->owned_by_self()) { @@ -2803,23 +2790,17 @@ ConcurrentMarkSweepGeneration::expand_and_allocate(size_t word_size, CMSSynchronousYieldRequest yr; assert(!tlab, "Can't deal with TLAB allocation"); MutexLockerEx x(freelistLock(), Mutex::_no_safepoint_check_flag); - expand(word_size*HeapWordSize, MinHeapDeltaBytes, - CMSExpansionCause::_satisfy_allocation); + expand_for_gc_cause(word_size*HeapWordSize, MinHeapDeltaBytes, CMSExpansionCause::_satisfy_allocation); if (GCExpandToAllocateDelayMillis > 0) { os::sleep(Thread::current(), GCExpandToAllocateDelayMillis, false); } return have_lock_and_allocate(word_size, tlab); } -// YSR: All of this generation expansion/shrinking stuff is an exact copy of -// TenuredGeneration, which makes me wonder if we should move this -// to CardGeneration and share it... -bool ConcurrentMarkSweepGeneration::expand(size_t bytes, size_t expand_bytes) { - return CardGeneration::expand(bytes, expand_bytes); -} - -void ConcurrentMarkSweepGeneration::expand(size_t bytes, size_t expand_bytes, - CMSExpansionCause::Cause cause) +void ConcurrentMarkSweepGeneration::expand_for_gc_cause( + size_t bytes, + size_t expand_bytes, + CMSExpansionCause::Cause cause) { bool success = expand(bytes, expand_bytes); @@ -2848,8 +2829,7 @@ HeapWord* ConcurrentMarkSweepGeneration::expand_and_par_lab_allocate(CMSParGCThr return NULL; } // Otherwise, we try expansion. - expand(word_sz*HeapWordSize, MinHeapDeltaBytes, - CMSExpansionCause::_allocate_par_lab); + expand_for_gc_cause(word_sz*HeapWordSize, MinHeapDeltaBytes, CMSExpansionCause::_allocate_par_lab); // Now go around the loop and try alloc again; // A competing par_promote might beat us to the expansion space, // so we may go around the loop again if promotion fails again. @@ -2876,8 +2856,7 @@ bool ConcurrentMarkSweepGeneration::expand_and_ensure_spooling_space( return false; } // Otherwise, we try expansion. - expand(refill_size_bytes, MinHeapDeltaBytes, - CMSExpansionCause::_allocate_par_spooling_space); + expand_for_gc_cause(refill_size_bytes, MinHeapDeltaBytes, CMSExpansionCause::_allocate_par_spooling_space); // Now go around the loop and try alloc again; // A competing allocation might beat us to the expansion space, // so we may go around the loop again if allocation fails again. @@ -2887,77 +2866,16 @@ bool ConcurrentMarkSweepGeneration::expand_and_ensure_spooling_space( } } - -void ConcurrentMarkSweepGeneration::shrink_by(size_t bytes) { - assert_locked_or_safepoint(ExpandHeap_lock); - // Shrink committed space - _virtual_space.shrink_by(bytes); - // Shrink space; this also shrinks the space's BOT - _cmsSpace->set_end((HeapWord*) _virtual_space.high()); - size_t new_word_size = heap_word_size(_cmsSpace->capacity()); - // Shrink the shared block offset array - _bts->resize(new_word_size); - MemRegion mr(_cmsSpace->bottom(), new_word_size); - // Shrink the card table - Universe::heap()->barrier_set()->resize_covered_region(mr); - - if (Verbose && PrintGC) { - size_t new_mem_size = _virtual_space.committed_size(); - size_t old_mem_size = new_mem_size + bytes; - gclog_or_tty->print_cr("Shrinking %s from " SIZE_FORMAT "K to " SIZE_FORMAT "K", - name(), old_mem_size/K, new_mem_size/K); - } -} - void ConcurrentMarkSweepGeneration::shrink(size_t bytes) { - assert_locked_or_safepoint(Heap_lock); - size_t size = ReservedSpace::page_align_size_down(bytes); // Only shrink if a compaction was done so that all the free space // in the generation is in a contiguous block at the end. - if (size > 0 && did_compact()) { - shrink_by(size); + if (did_compact()) { + CardGeneration::shrink(bytes); } } -bool ConcurrentMarkSweepGeneration::grow_by(size_t bytes) { +void ConcurrentMarkSweepGeneration::assert_correct_size_change_locking() { assert_locked_or_safepoint(Heap_lock); - bool result = _virtual_space.expand_by(bytes); - if (result) { - size_t new_word_size = - heap_word_size(_virtual_space.committed_size()); - MemRegion mr(_cmsSpace->bottom(), new_word_size); - _bts->resize(new_word_size); // resize the block offset shared array - Universe::heap()->barrier_set()->resize_covered_region(mr); - // Hmmmm... why doesn't CFLS::set_end verify locking? - // This is quite ugly; FIX ME XXX - _cmsSpace->assert_locked(freelistLock()); - _cmsSpace->set_end((HeapWord*)_virtual_space.high()); - - // update the space and generation capacity counters - if (UsePerfData) { - _space_counters->update_capacity(); - _gen_counters->update_all(); - } - - if (Verbose && PrintGC) { - size_t new_mem_size = _virtual_space.committed_size(); - size_t old_mem_size = new_mem_size - bytes; - gclog_or_tty->print_cr("Expanding %s from " SIZE_FORMAT "K by " SIZE_FORMAT "K to " SIZE_FORMAT "K", - name(), old_mem_size/K, bytes/K, new_mem_size/K); - } - } - return result; -} - -bool ConcurrentMarkSweepGeneration::grow_to_reserved() { - assert_locked_or_safepoint(Heap_lock); - bool success = true; - const size_t remaining_bytes = _virtual_space.uncommitted_size(); - if (remaining_bytes > 0) { - success = grow_by(remaining_bytes); - DEBUG_ONLY(if (!success) warning("grow to reserved failed");) - } - return success; } void ConcurrentMarkSweepGeneration::shrink_free_list_by(size_t bytes) { @@ -3084,7 +3002,7 @@ void CMSCollector::checkpointRootsInitial() { Mutex::_no_safepoint_check_flag); checkpointRootsInitialWork(); // enable ("weak") refs discovery - rp->enable_discovery(true /*verify_disabled*/, true /*check_no_refs*/); + rp->enable_discovery(); _collectorState = Marking; } SpecializationStats::print(); @@ -6031,7 +5949,8 @@ HeapWord* CMSCollector::next_card_start_after_block(HeapWord* addr) const { CMSBitMap::CMSBitMap(int shifter, int mutex_rank, const char* mutex_name): _bm(), _shifter(shifter), - _lock(mutex_rank >= 0 ? new Mutex(mutex_rank, mutex_name, true) : NULL) + _lock(mutex_rank >= 0 ? new Mutex(mutex_rank, mutex_name, true, + Monitor::_safepoint_check_sometimes) : NULL) { _bmStartWord = 0; _bmWordSize = 0; diff --git a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp index 826cfd5def2..3ca036494d4 100644 --- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 @@ -30,9 +30,10 @@ #include "gc_implementation/shared/gcStats.hpp" #include "gc_implementation/shared/gcWhen.hpp" #include "gc_implementation/shared/generationCounters.hpp" +#include "memory/cardGeneration.hpp" #include "memory/freeBlockDictionary.hpp" -#include "memory/generation.hpp" #include "memory/iterator.hpp" +#include "memory/space.hpp" #include "runtime/mutexLocker.hpp" #include "runtime/virtualspace.hpp" #include "services/memoryService.hpp" @@ -171,9 +172,7 @@ class CMSBitMap VALUE_OBJ_CLASS_SPEC { // Represents a marking stack used by the CMS collector. // Ideally this should be GrowableArray<> just like MSC's marking stack(s). class CMSMarkStack: public CHeapObj { - // friend class CMSCollector; // To get at expansion stats further below. - // VirtualSpace _virtual_space; // Space for the stack oop* _base; // Bottom of stack @@ -188,7 +187,8 @@ class CMSMarkStack: public CHeapObj { public: CMSMarkStack(): - _par_lock(Mutex::event, "CMSMarkStack._par_lock", true), + _par_lock(Mutex::event, "CMSMarkStack._par_lock", true, + Monitor::_safepoint_check_never), _hit_limit(0), _failed_double(0) {} @@ -1031,6 +1031,9 @@ class ConcurrentMarkSweepGeneration: public CardGeneration { void set_expansion_cause(CMSExpansionCause::Cause v) { _expansion_cause = v;} CMSExpansionCause::Cause expansion_cause() const { return _expansion_cause; } + // Accessing spaces + CompactibleSpace* space() const { return (CompactibleSpace*)_cmsSpace; } + private: // For parallel young-gen GC support. CMSParGCThreadState** _par_gc_thread_states; @@ -1064,6 +1067,10 @@ class ConcurrentMarkSweepGeneration: public CardGeneration { double initiating_occupancy() const { return _initiating_occupancy; } void init_initiating_occupancy(intx io, uintx tr); + void expand_for_gc_cause(size_t bytes, size_t expand_bytes, CMSExpansionCause::Cause cause); + + void assert_correct_size_change_locking(); + public: ConcurrentMarkSweepGeneration(ReservedSpace rs, size_t initial_byte_size, int level, CardTableRS* ct, @@ -1100,23 +1107,14 @@ class ConcurrentMarkSweepGeneration: public CardGeneration { // Override virtual void ref_processor_init(); - // Grow generation by specified size (returns false if unable to grow) - bool grow_by(size_t bytes); - // Grow generation to reserved size. - bool grow_to_reserved(); - void clear_expansion_cause() { _expansion_cause = CMSExpansionCause::_no_expansion; } // Space enquiries - size_t capacity() const; - size_t used() const; - size_t free() const; double occupancy() const { return ((double)used())/((double)capacity()); } size_t contiguous_available() const; size_t unsafe_max_alloc_nogc() const; // over-rides - MemRegion used_region() const; MemRegion used_region_at_save_marks() const; // Does a "full" (forced) collection invoked on this generation collect @@ -1127,10 +1125,6 @@ class ConcurrentMarkSweepGeneration: public CardGeneration { return !ScavengeBeforeFullGC; } - void space_iterate(SpaceClosure* blk, bool usedOnly = false); - - // Support for compaction - CompactibleSpace* first_compaction_space() const; // Adjust quantities in the generation affected by // the compaction. void reset_after_compaction(); @@ -1190,18 +1184,13 @@ class ConcurrentMarkSweepGeneration: public CardGeneration { } // Allocation failure - void expand(size_t bytes, size_t expand_bytes, - CMSExpansionCause::Cause cause); - virtual bool expand(size_t bytes, size_t expand_bytes); void shrink(size_t bytes); - void shrink_by(size_t bytes); HeapWord* expand_and_par_lab_allocate(CMSParGCThreadState* ps, size_t word_sz); bool expand_and_ensure_spooling_space(PromotionInfo* promo); // Iteration support and related enquiries void save_marks(); bool no_allocs_since_save_marks(); - void younger_refs_iterate(OopsInGenClosure* cl); // Iteration support specific to CMS generations void save_sweep_limit(); diff --git a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.inline.hpp b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.inline.hpp index dc76d1bc884..bc552f78420 100644 --- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.inline.hpp +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 @@ -369,22 +369,6 @@ inline void ConcurrentMarkSweepGeneration::save_sweep_limit() { cmsSpace()->save_sweep_limit(); } -inline size_t ConcurrentMarkSweepGeneration::capacity() const { - return _cmsSpace->capacity(); -} - -inline size_t ConcurrentMarkSweepGeneration::used() const { - return _cmsSpace->used(); -} - -inline size_t ConcurrentMarkSweepGeneration::free() const { - return _cmsSpace->free(); -} - -inline MemRegion ConcurrentMarkSweepGeneration::used_region() const { - return _cmsSpace->used_region(); -} - inline MemRegion ConcurrentMarkSweepGeneration::used_region_at_save_marks() const { return _cmsSpace->used_region_at_save_marks(); } diff --git a/hotspot/src/share/vm/gc_implementation/g1/concurrentG1RefineThread.cpp b/hotspot/src/share/vm/gc_implementation/g1/concurrentG1RefineThread.cpp index 458c3e28c3f..56ae3c2a7f2 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentG1RefineThread.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentG1RefineThread.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 @@ -52,7 +52,8 @@ ConcurrentG1RefineThread(ConcurrentG1Refine* cg1r, ConcurrentG1RefineThread *nex // The 0th worker in notified by mutator threads and has a special monitor. // The last worker is used for young gen rset size sampling. if (worker_id > 0) { - _monitor = new Monitor(Mutex::nonleaf, "Refinement monitor", true); + _monitor = new Monitor(Mutex::nonleaf, "Refinement monitor", true, + Monitor::_safepoint_check_never); } else { _monitor = DirtyCardQ_CBL_mon; } diff --git a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp index ce8ab529c7c..6bb8b5de63c 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp @@ -971,7 +971,7 @@ void ConcurrentMark::checkpointRootsInitialPost() { // Start Concurrent Marking weak-reference discovery. ReferenceProcessor* rp = g1h->ref_processor_cm(); // enable ("weak") refs discovery - rp->enable_discovery(true /*verify_disabled*/, true /*verify_no_refs*/); + rp->enable_discovery(); rp->setup_policy(false); // snapshot the soft ref policy to be used in this cycle SATBMarkQueueSet& satb_mq_set = JavaThread::satb_mark_queue_set(); diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1AllocRegion.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1AllocRegion.cpp index 9d2f06255a6..697a4027577 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1AllocRegion.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1AllocRegion.cpp @@ -254,25 +254,23 @@ void MutatorAllocRegion::retire_region(HeapRegion* alloc_region, HeapRegion* SurvivorGCAllocRegion::allocate_new_region(size_t word_size, bool force) { assert(!force, "not supported for GC alloc regions"); - return _g1h->new_gc_alloc_region(word_size, count(), GCAllocForSurvived); + return _g1h->new_gc_alloc_region(word_size, count(), InCSetState::Young); } void SurvivorGCAllocRegion::retire_region(HeapRegion* alloc_region, size_t allocated_bytes) { - _g1h->retire_gc_alloc_region(alloc_region, allocated_bytes, - GCAllocForSurvived); + _g1h->retire_gc_alloc_region(alloc_region, allocated_bytes, InCSetState::Young); } HeapRegion* OldGCAllocRegion::allocate_new_region(size_t word_size, bool force) { assert(!force, "not supported for GC alloc regions"); - return _g1h->new_gc_alloc_region(word_size, count(), GCAllocForTenured); + return _g1h->new_gc_alloc_region(word_size, count(), InCSetState::Old); } void OldGCAllocRegion::retire_region(HeapRegion* alloc_region, size_t allocated_bytes) { - _g1h->retire_gc_alloc_region(alloc_region, allocated_bytes, - GCAllocForTenured); + _g1h->retire_gc_alloc_region(alloc_region, allocated_bytes, InCSetState::Old); } HeapRegion* OldGCAllocRegion::release() { diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1Allocator.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1Allocator.cpp index 695feeea6f6..45ab111b720 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1Allocator.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1Allocator.cpp @@ -113,15 +113,16 @@ void G1DefaultAllocator::abandon_gc_alloc_regions() { G1ParGCAllocBuffer::G1ParGCAllocBuffer(size_t gclab_word_size) : ParGCAllocBuffer(gclab_word_size), _retired(true) { } -HeapWord* G1ParGCAllocator::allocate_slow(GCAllocPurpose purpose, size_t word_sz, AllocationContext_t context) { - HeapWord* obj = NULL; - size_t gclab_word_size = _g1h->desired_plab_sz(purpose); +HeapWord* G1ParGCAllocator::allocate_direct_or_new_plab(InCSetState dest, + size_t word_sz, + AllocationContext_t context) { + size_t gclab_word_size = _g1h->desired_plab_sz(dest); if (word_sz * 100 < gclab_word_size * ParallelGCBufferWastePct) { - G1ParGCAllocBuffer* alloc_buf = alloc_buffer(purpose, context); + G1ParGCAllocBuffer* alloc_buf = alloc_buffer(dest, context); add_to_alloc_buffer_waste(alloc_buf->words_remaining()); alloc_buf->retire(false /* end_of_gc */, false /* retain */); - HeapWord* buf = _g1h->par_allocate_during_gc(purpose, gclab_word_size, context); + HeapWord* buf = _g1h->par_allocate_during_gc(dest, gclab_word_size, context); if (buf == NULL) { return NULL; // Let caller handle allocation failure. } @@ -129,30 +130,33 @@ HeapWord* G1ParGCAllocator::allocate_slow(GCAllocPurpose purpose, size_t word_sz alloc_buf->set_word_size(gclab_word_size); alloc_buf->set_buf(buf); - obj = alloc_buf->allocate(word_sz); + HeapWord* const obj = alloc_buf->allocate(word_sz); assert(obj != NULL, "buffer was definitely big enough..."); + return obj; } else { - obj = _g1h->par_allocate_during_gc(purpose, word_sz, context); + return _g1h->par_allocate_during_gc(dest, word_sz, context); } - return obj; } G1DefaultParGCAllocator::G1DefaultParGCAllocator(G1CollectedHeap* g1h) : - G1ParGCAllocator(g1h), - _surviving_alloc_buffer(g1h->desired_plab_sz(GCAllocForSurvived)), - _tenured_alloc_buffer(g1h->desired_plab_sz(GCAllocForTenured)) { - - _alloc_buffers[GCAllocForSurvived] = &_surviving_alloc_buffer; - _alloc_buffers[GCAllocForTenured] = &_tenured_alloc_buffer; - + G1ParGCAllocator(g1h), + _surviving_alloc_buffer(g1h->desired_plab_sz(InCSetState::Young)), + _tenured_alloc_buffer(g1h->desired_plab_sz(InCSetState::Old)) { + for (uint state = 0; state < InCSetState::Num; state++) { + _alloc_buffers[state] = NULL; + } + _alloc_buffers[InCSetState::Young] = &_surviving_alloc_buffer; + _alloc_buffers[InCSetState::Old] = &_tenured_alloc_buffer; } void G1DefaultParGCAllocator::retire_alloc_buffers() { - for (int ap = 0; ap < GCAllocPurposeCount; ++ap) { - size_t waste = _alloc_buffers[ap]->words_remaining(); - add_to_alloc_buffer_waste(waste); - _alloc_buffers[ap]->flush_stats_and_retire(_g1h->stats_for_purpose((GCAllocPurpose)ap), - true /* end_of_gc */, - false /* retain */); + for (uint state = 0; state < InCSetState::Num; state++) { + G1ParGCAllocBuffer* const buf = _alloc_buffers[state]; + if (buf != NULL) { + add_to_alloc_buffer_waste(buf->words_remaining()); + buf->flush_stats_and_retire(_g1h->alloc_buffer_stats(state), + true /* end_of_gc */, + false /* retain */); + } } } diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1Allocator.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1Allocator.hpp index 151342c47a8..b32a4191dca 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1Allocator.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1Allocator.hpp @@ -27,14 +27,9 @@ #include "gc_implementation/g1/g1AllocationContext.hpp" #include "gc_implementation/g1/g1AllocRegion.hpp" +#include "gc_implementation/g1/g1InCSetState.hpp" #include "gc_implementation/shared/parGCAllocBuffer.hpp" -enum GCAllocPurpose { - GCAllocForTenured, - GCAllocForSurvived, - GCAllocPurposeCount -}; - // Base class for G1 allocators. class G1Allocator : public CHeapObj { friend class VMStructs; @@ -178,20 +173,40 @@ class G1ParGCAllocator : public CHeapObj { protected: G1CollectedHeap* _g1h; + // The survivor alignment in effect in bytes. + // == 0 : don't align survivors + // != 0 : align survivors to that alignment + // These values were chosen to favor the non-alignment case since some + // architectures have a special compare against zero instructions. + const uint _survivor_alignment_bytes; + size_t _alloc_buffer_waste; size_t _undo_waste; void add_to_alloc_buffer_waste(size_t waste) { _alloc_buffer_waste += waste; } void add_to_undo_waste(size_t waste) { _undo_waste += waste; } - HeapWord* allocate_slow(GCAllocPurpose purpose, size_t word_sz, AllocationContext_t context); - virtual void retire_alloc_buffers() = 0; - virtual G1ParGCAllocBuffer* alloc_buffer(GCAllocPurpose purpose, AllocationContext_t context) = 0; + virtual G1ParGCAllocBuffer* alloc_buffer(InCSetState dest, AllocationContext_t context) = 0; + + // Calculate the survivor space object alignment in bytes. Returns that or 0 if + // there are no restrictions on survivor alignment. + static uint calc_survivor_alignment_bytes() { + assert(SurvivorAlignmentInBytes >= ObjectAlignmentInBytes, "sanity"); + if (SurvivorAlignmentInBytes == ObjectAlignmentInBytes) { + // No need to align objects in the survivors differently, return 0 + // which means "survivor alignment is not used". + return 0; + } else { + assert(SurvivorAlignmentInBytes > 0, "sanity"); + return SurvivorAlignmentInBytes; + } + } public: G1ParGCAllocator(G1CollectedHeap* g1h) : - _g1h(g1h), _alloc_buffer_waste(0), _undo_waste(0) { + _g1h(g1h), _survivor_alignment_bytes(calc_survivor_alignment_bytes()), + _alloc_buffer_waste(0), _undo_waste(0) { } static G1ParGCAllocator* create_allocator(G1CollectedHeap* g1h); @@ -199,24 +214,40 @@ public: size_t alloc_buffer_waste() { return _alloc_buffer_waste; } size_t undo_waste() {return _undo_waste; } - HeapWord* allocate(GCAllocPurpose purpose, size_t word_sz, AllocationContext_t context) { - HeapWord* obj = NULL; - if (purpose == GCAllocForSurvived) { - obj = alloc_buffer(purpose, context)->allocate_aligned(word_sz, SurvivorAlignmentInBytes); + // Allocate word_sz words in dest, either directly into the regions or by + // allocating a new PLAB. Returns the address of the allocated memory, NULL if + // not successful. + HeapWord* allocate_direct_or_new_plab(InCSetState dest, + size_t word_sz, + AllocationContext_t context); + + // Allocate word_sz words in the PLAB of dest. Returns the address of the + // allocated memory, NULL if not successful. + HeapWord* plab_allocate(InCSetState dest, + size_t word_sz, + AllocationContext_t context) { + G1ParGCAllocBuffer* buffer = alloc_buffer(dest, context); + if (_survivor_alignment_bytes == 0) { + return buffer->allocate(word_sz); } else { - obj = alloc_buffer(purpose, context)->allocate(word_sz); + return buffer->allocate_aligned(word_sz, _survivor_alignment_bytes); } + } + + HeapWord* allocate(InCSetState dest, size_t word_sz, + AllocationContext_t context) { + HeapWord* const obj = plab_allocate(dest, word_sz, context); if (obj != NULL) { return obj; } - return allocate_slow(purpose, word_sz, context); + return allocate_direct_or_new_plab(dest, word_sz, context); } - void undo_allocation(GCAllocPurpose purpose, HeapWord* obj, size_t word_sz, AllocationContext_t context) { - if (alloc_buffer(purpose, context)->contains(obj)) { - assert(alloc_buffer(purpose, context)->contains(obj + word_sz - 1), + void undo_allocation(InCSetState dest, HeapWord* obj, size_t word_sz, AllocationContext_t context) { + if (alloc_buffer(dest, context)->contains(obj)) { + assert(alloc_buffer(dest, context)->contains(obj + word_sz - 1), "should contain whole object"); - alloc_buffer(purpose, context)->undo_allocation(obj, word_sz); + alloc_buffer(dest, context)->undo_allocation(obj, word_sz); } else { CollectedHeap::fill_with_object(obj, word_sz); add_to_undo_waste(word_sz); @@ -227,13 +258,17 @@ public: class G1DefaultParGCAllocator : public G1ParGCAllocator { G1ParGCAllocBuffer _surviving_alloc_buffer; G1ParGCAllocBuffer _tenured_alloc_buffer; - G1ParGCAllocBuffer* _alloc_buffers[GCAllocPurposeCount]; + G1ParGCAllocBuffer* _alloc_buffers[InCSetState::Num]; public: G1DefaultParGCAllocator(G1CollectedHeap* g1h); - virtual G1ParGCAllocBuffer* alloc_buffer(GCAllocPurpose purpose, AllocationContext_t context) { - return _alloc_buffers[purpose]; + virtual G1ParGCAllocBuffer* alloc_buffer(InCSetState dest, AllocationContext_t context) { + assert(dest.is_valid(), + err_msg("Allocation buffer index out-of-bounds: " CSETSTATE_FORMAT, dest.value())); + assert(_alloc_buffers[dest.value()] != NULL, + err_msg("Allocation buffer is NULL: " CSETSTATE_FORMAT, dest.value())); + return _alloc_buffers[dest.value()]; } virtual void retire_alloc_buffers() ; diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp index 875ffdbc311..b889a3622ec 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp @@ -352,7 +352,7 @@ void YoungList::print() { } void G1RegionMappingChangedListener::reset_from_card_cache(uint start_idx, size_t num_regions) { - OtherRegionsTable::invalidate(start_idx, num_regions); + HeapRegionRemSet::invalidate_from_card_cache(start_idx, num_regions); } void G1RegionMappingChangedListener::on_commit(uint start_idx, size_t num_regions, bool zero_filled) { @@ -1301,7 +1301,7 @@ bool G1CollectedHeap::do_collection(bool explicit_gc, // Temporarily clear the STW ref processor's _is_alive_non_header field. ReferenceProcessorIsAliveMutator stw_rp_is_alive_null(ref_processor_stw(), NULL); - ref_processor_stw()->enable_discovery(true /*verify_disabled*/, true /*verify_no_refs*/); + ref_processor_stw()->enable_discovery(); ref_processor_stw()->setup_policy(do_clear_all_soft_refs); // Do collection work @@ -1886,13 +1886,12 @@ jint G1CollectedHeap::initialize() { initialize_reserved_region((HeapWord*)heap_rs.base(), (HeapWord*)(heap_rs.base() + heap_rs.size())); - // Create the gen rem set (and barrier set) for the entire reserved region. - _rem_set = collector_policy()->create_rem_set(reserved_region()); - set_barrier_set(rem_set()->bs()); - if (!barrier_set()->is_a(BarrierSet::G1SATBCTLogging)) { - vm_exit_during_initialization("G1 requires a G1SATBLoggingCardTableModRefBS"); - return JNI_ENOMEM; - } + // Create the barrier set for the entire reserved region. + G1SATBCardTableLoggingModRefBS* bs + = new G1SATBCardTableLoggingModRefBS(reserved_region()); + bs->initialize(); + assert(bs->is_a(BarrierSet::G1SATBCTLogging), "sanity"); + set_barrier_set(bs); // Also create a G1 rem set. _g1_rem_set = new G1RemSet(this, g1_barrier_set()); @@ -3153,8 +3152,6 @@ void G1CollectedHeap::verify(bool silent, VerifyOption vo) { failures = true; } } - if (!silent) gclog_or_tty->print("RemSet "); - rem_set()->verify(); if (G1StringDedup::is_enabled()) { if (!silent) gclog_or_tty->print("StrDedup "); @@ -3750,8 +3747,7 @@ G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) { // reference processing currently works in G1. // Enable discovery in the STW reference processor - ref_processor_stw()->enable_discovery(true /*verify_disabled*/, - true /*verify_no_refs*/); + ref_processor_stw()->enable_discovery(); { // We want to temporarily turn off discovery by the @@ -3819,6 +3815,8 @@ G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) { register_humongous_regions_with_in_cset_fast_test(); + assert(check_cset_fast_test(), "Inconsistency in the InCSetState table."); + _cm->note_start_of_gc(); // We should not verify the per-thread SATB buffers given that // we have not filtered them yet (we'll do so during the @@ -4048,29 +4046,6 @@ G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) { return true; } -size_t G1CollectedHeap::desired_plab_sz(GCAllocPurpose purpose) -{ - size_t gclab_word_size; - switch (purpose) { - case GCAllocForSurvived: - gclab_word_size = _survivor_plab_stats.desired_plab_sz(); - break; - case GCAllocForTenured: - gclab_word_size = _old_plab_stats.desired_plab_sz(); - break; - default: - assert(false, "unknown GCAllocPurpose"); - gclab_word_size = _old_plab_stats.desired_plab_sz(); - break; - } - - // Prevent humongous PLAB sizes for two reasons: - // * PLABs are allocated using a similar paths as oops, but should - // never be in a humongous region - // * Allowing humongous PLABs needlessly churns the region free lists - return MIN2(_humongous_object_threshold_in_words, gclab_word_size); -} - void G1CollectedHeap::init_for_evac_failure(OopsInHeapRegionClosure* cl) { _drain_in_progress = false; set_evac_failure_closure(cl); @@ -4196,35 +4171,6 @@ void G1CollectedHeap::preserve_mark_if_necessary(oop obj, markOop m) { } } -HeapWord* G1CollectedHeap::par_allocate_during_gc(GCAllocPurpose purpose, - size_t word_size, - AllocationContext_t context) { - if (purpose == GCAllocForSurvived) { - HeapWord* result = survivor_attempt_allocation(word_size, context); - if (result != NULL) { - return result; - } else { - // Let's try to allocate in the old gen in case we can fit the - // object there. - return old_attempt_allocation(word_size, context); - } - } else { - assert(purpose == GCAllocForTenured, "sanity"); - HeapWord* result = old_attempt_allocation(word_size, context); - if (result != NULL) { - return result; - } else { - // Let's try to allocate in the survivors in case we can fit the - // object there. - return survivor_attempt_allocation(word_size, context); - } - } - - ShouldNotReachHere(); - // Trying to keep some compilers happy. - return NULL; -} - void G1ParCopyHelper::mark_object(oop obj) { assert(!_g1->heap_region_containing(obj)->in_collection_set(), "should not mark objects in the CSet"); @@ -4267,15 +4213,14 @@ void G1ParCopyClosure::do_oop_work(T* p) { assert(_worker_id == _par_scan_state->queue_num(), "sanity"); - G1CollectedHeap::in_cset_state_t state = _g1->in_cset_state(obj); - - if (state == G1CollectedHeap::InCSet) { + const InCSetState state = _g1->in_cset_state(obj); + if (state.is_in_cset()) { oop forwardee; markOop m = obj->mark(); if (m->is_marked()) { forwardee = (oop) m->decode_pointer(); } else { - forwardee = _par_scan_state->copy_to_survivor_space(obj, m); + forwardee = _par_scan_state->copy_to_survivor_space(state, obj, m); } assert(forwardee != NULL, "forwardee should not be NULL"); oopDesc::encode_store_heap_oop(p, forwardee); @@ -4289,7 +4234,7 @@ void G1ParCopyClosure::do_oop_work(T* p) { do_klass_barrier(p, forwardee); } } else { - if (state == G1CollectedHeap::IsHumongous) { + if (state.is_humongous()) { _g1->set_humongous_is_live(obj); } // The object is not in collection set. If we're a root scanning @@ -4609,7 +4554,7 @@ void G1CollectedHeap:: g1_process_roots(OopClosure* scan_non_heap_roots, OopClosure* scan_non_heap_weak_roots, - OopsInHeapRegionClosure* scan_rs, + G1ParPushHeapRSClosure* scan_rs, CLDClosure* scan_strong_clds, CLDClosure* scan_weak_clds, CodeBlobClosure* scan_strong_code, @@ -4933,7 +4878,7 @@ private: } }; -Monitor* G1CodeCacheUnloadingTask::_lock = new Monitor(Mutex::leaf, "Code Cache Unload lock"); +Monitor* G1CodeCacheUnloadingTask::_lock = new Monitor(Mutex::leaf, "Code Cache Unload lock", false, Monitor::_safepoint_check_never); class G1KlassCleaningTask : public StackObj { BoolObjectClosure* _is_alive; @@ -5145,17 +5090,17 @@ public: oop obj = *p; assert(obj != NULL, "the caller should have filtered out NULL values"); - G1CollectedHeap::in_cset_state_t cset_state = _g1->in_cset_state(obj); - if (cset_state == G1CollectedHeap::InNeither) { + const InCSetState cset_state = _g1->in_cset_state(obj); + if (!cset_state.is_in_cset_or_humongous()) { return; } - if (cset_state == G1CollectedHeap::InCSet) { + if (cset_state.is_in_cset()) { assert( obj->is_forwarded(), "invariant" ); *p = obj->forwardee(); } else { assert(!obj->is_forwarded(), "invariant" ); - assert(cset_state == G1CollectedHeap::IsHumongous, - err_msg("Only allowed InCSet state is IsHumongous, but is %d", cset_state)); + assert(cset_state.is_humongous(), + err_msg("Only allowed InCSet state is IsHumongous, but is %d", cset_state.value())); _g1->set_humongous_is_live(obj); } } @@ -5640,8 +5585,6 @@ void G1CollectedHeap::evacuate_collection_set(EvacuationInfo& evacuation_info) { init_for_evac_failure(NULL); - rem_set()->prepare_for_younger_refs_iterate(true); - assert(dirty_card_queue_set().completed_buffers_num() == 0, "Should be empty"); double start_par_time_sec = os::elapsedTime(); double end_par_time_sec; @@ -5951,6 +5894,70 @@ void G1CollectedHeap::check_bitmaps(const char* caller) { heap_region_iterate(&cl); guarantee(!cl.failures(), "bitmap verification"); } + +class G1CheckCSetFastTableClosure : public HeapRegionClosure { + private: + bool _failures; + public: + G1CheckCSetFastTableClosure() : HeapRegionClosure(), _failures(false) { } + + virtual bool doHeapRegion(HeapRegion* hr) { + uint i = hr->hrm_index(); + InCSetState cset_state = (InCSetState) G1CollectedHeap::heap()->_in_cset_fast_test.get_by_index(i); + if (hr->is_humongous()) { + if (hr->in_collection_set()) { + gclog_or_tty->print_cr("\n## humongous region %u in CSet", i); + _failures = true; + return true; + } + if (cset_state.is_in_cset()) { + gclog_or_tty->print_cr("\n## inconsistent cset state %d for humongous region %u", cset_state.value(), i); + _failures = true; + return true; + } + if (hr->is_continues_humongous() && cset_state.is_humongous()) { + gclog_or_tty->print_cr("\n## inconsistent cset state %d for continues humongous region %u", cset_state.value(), i); + _failures = true; + return true; + } + } else { + if (cset_state.is_humongous()) { + gclog_or_tty->print_cr("\n## inconsistent cset state %d for non-humongous region %u", cset_state.value(), i); + _failures = true; + return true; + } + if (hr->in_collection_set() != cset_state.is_in_cset()) { + gclog_or_tty->print_cr("\n## in CSet %d / cset state %d inconsistency for region %u", + hr->in_collection_set(), cset_state.value(), i); + _failures = true; + return true; + } + if (cset_state.is_in_cset()) { + if (hr->is_young() != (cset_state.is_young())) { + gclog_or_tty->print_cr("\n## is_young %d / cset state %d inconsistency for region %u", + hr->is_young(), cset_state.value(), i); + _failures = true; + return true; + } + if (hr->is_old() != (cset_state.is_old())) { + gclog_or_tty->print_cr("\n## is_old %d / cset state %d inconsistency for region %u", + hr->is_old(), cset_state.value(), i); + _failures = true; + return true; + } + } + } + return false; + } + + bool failures() const { return _failures; } +}; + +bool G1CollectedHeap::check_cset_fast_test() { + G1CheckCSetFastTableClosure cl; + _hrm.iterate(&cl); + return !cl.failures(); +} #endif // PRODUCT void G1CollectedHeap::cleanUpCardTable() { @@ -6519,20 +6526,20 @@ void G1CollectedHeap::set_par_threads() { HeapRegion* G1CollectedHeap::new_gc_alloc_region(size_t word_size, uint count, - GCAllocPurpose ap) { + InCSetState dest) { assert(FreeList_lock->owned_by_self(), "pre-condition"); - if (count < g1_policy()->max_regions(ap)) { - bool survivor = (ap == GCAllocForSurvived); + if (count < g1_policy()->max_regions(dest)) { + const bool is_survivor = (dest.is_young()); HeapRegion* new_alloc_region = new_region(word_size, - !survivor, + !is_survivor, true /* do_expand */); if (new_alloc_region != NULL) { // We really only need to do this for old regions given that we // should never scan survivors. But it doesn't hurt to do it // for survivors too. new_alloc_region->record_timestamp(); - if (survivor) { + if (is_survivor) { new_alloc_region->set_survivor(); _hr_printer.alloc(new_alloc_region, G1HRPrinter::Survivor); check_bitmaps("Survivor Region Allocation", new_alloc_region); @@ -6544,8 +6551,6 @@ HeapRegion* G1CollectedHeap::new_gc_alloc_region(size_t word_size, bool during_im = g1_policy()->during_initial_mark_pause(); new_alloc_region->note_start_of_copying(during_im); return new_alloc_region; - } else { - g1_policy()->note_alloc_region_limit_reached(ap); } } return NULL; @@ -6553,11 +6558,11 @@ HeapRegion* G1CollectedHeap::new_gc_alloc_region(size_t word_size, void G1CollectedHeap::retire_gc_alloc_region(HeapRegion* alloc_region, size_t allocated_bytes, - GCAllocPurpose ap) { + InCSetState dest) { bool during_im = g1_policy()->during_initial_mark_pause(); alloc_region->note_end_of_copying(during_im); g1_policy()->record_bytes_copied_during_gc(allocated_bytes); - if (ap == GCAllocForSurvived) { + if (dest.is_young()) { young_list()->add_survivor_region(alloc_region); } else { _old_set.add(alloc_region); diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp index 444706b671e..2d1921da897 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp @@ -32,6 +32,7 @@ #include "gc_implementation/g1/g1AllocRegion.hpp" #include "gc_implementation/g1/g1BiasedArray.hpp" #include "gc_implementation/g1/g1HRPrinter.hpp" +#include "gc_implementation/g1/g1InCSetState.hpp" #include "gc_implementation/g1/g1MonitoringSupport.hpp" #include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp" #include "gc_implementation/g1/g1YCTypes.hpp" @@ -213,6 +214,9 @@ class G1CollectedHeap : public SharedHeap { friend class G1MarkSweep; friend class HeapRegionClaimer; + // Testing classes. + friend class G1CheckCSetFastTableClosure; + private: // The one and only G1CollectedHeap, so static functions can find it. static G1CollectedHeap* _g1h; @@ -547,15 +551,9 @@ protected: // allocation region, either by picking one or expanding the // heap, and then allocate a block of the given size. The block // may not be a humongous - it must fit into a single heap region. - HeapWord* par_allocate_during_gc(GCAllocPurpose purpose, - size_t word_size, - AllocationContext_t context); - - HeapWord* allocate_during_gc_slow(GCAllocPurpose purpose, - HeapRegion* alloc_region, - bool par, - size_t word_size); - + inline HeapWord* par_allocate_during_gc(InCSetState dest, + size_t word_size, + AllocationContext_t context); // Ensure that no further allocations can happen in "r", bearing in mind // that parallel threads might be attempting allocations. void par_allocate_remaining_space(HeapRegion* r); @@ -577,9 +575,9 @@ protected: // For GC alloc regions. HeapRegion* new_gc_alloc_region(size_t word_size, uint count, - GCAllocPurpose ap); + InCSetState dest); void retire_gc_alloc_region(HeapRegion* alloc_region, - size_t allocated_bytes, GCAllocPurpose ap); + size_t allocated_bytes, InCSetState dest); // - if explicit_gc is true, the GC is for a System.gc() or a heap // inspection request and should collect the entire heap @@ -640,26 +638,11 @@ public: // (Rounds up to a HeapRegion boundary.) bool expand(size_t expand_bytes); - // Returns the PLAB statistics given a purpose. - PLABStats* stats_for_purpose(GCAllocPurpose purpose) { - PLABStats* stats = NULL; + // Returns the PLAB statistics for a given destination. + inline PLABStats* alloc_buffer_stats(InCSetState dest); - switch (purpose) { - case GCAllocForSurvived: - stats = &_survivor_plab_stats; - break; - case GCAllocForTenured: - stats = &_old_plab_stats; - break; - default: - assert(false, "unrecognized GCAllocPurpose"); - } - - return stats; - } - - // Determines PLAB size for a particular allocation purpose. - size_t desired_plab_sz(GCAllocPurpose purpose); + // Determines PLAB size for a given destination. + inline size_t desired_plab_sz(InCSetState dest); inline AllocationContextStats& allocation_context_stats(); @@ -683,8 +666,11 @@ public: void register_humongous_regions_with_in_cset_fast_test(); // We register a region with the fast "in collection set" test. We // simply set to true the array slot corresponding to this region. - void register_region_with_in_cset_fast_test(HeapRegion* r) { - _in_cset_fast_test.set_in_cset(r->hrm_index()); + void register_young_region_with_in_cset_fast_test(HeapRegion* r) { + _in_cset_fast_test.set_in_young(r->hrm_index()); + } + void register_old_region_with_in_cset_fast_test(HeapRegion* r) { + _in_cset_fast_test.set_in_old(r->hrm_index()); } // This is a fast test on whether a reference points into the @@ -821,7 +807,7 @@ protected: // In the sequential case this param will be ignored. void g1_process_roots(OopClosure* scan_non_heap_roots, OopClosure* scan_non_heap_weak_roots, - OopsInHeapRegionClosure* scan_rs, + G1ParPushHeapRSClosure* scan_rs, CLDClosure* scan_strong_clds, CLDClosure* scan_weak_clds, CodeBlobClosure* scan_strong_code, @@ -1181,6 +1167,9 @@ public: // appropriate error messages and crash. void check_bitmaps(const char* caller) PRODUCT_RETURN; + // Do sanity check on the contents of the in-cset fast test table. + bool check_cset_fast_test() PRODUCT_RETURN_( return true; ); + // verify_region_sets() performs verification over the region // lists. It will be compiled in the product code to be used when // necessary (i.e., during heap verification). @@ -1276,53 +1265,15 @@ public: inline bool is_in_cset_or_humongous(const oop obj); - enum in_cset_state_t { - InNeither, // neither in collection set nor humongous - InCSet, // region is in collection set only - IsHumongous // region is a humongous start region - }; private: - // Instances of this class are used for quick tests on whether a reference points - // into the collection set or is a humongous object (points into a humongous - // object). - // Each of the array's elements denotes whether the corresponding region is in - // the collection set or a humongous region. - // We use this to quickly reclaim humongous objects: by making a humongous region - // succeed this test, we sort-of add it to the collection set. During the reference - // iteration closures, when we see a humongous region, we simply mark it as - // referenced, i.e. live. - class G1FastCSetBiasedMappedArray : public G1BiasedMappedArray { - protected: - char default_value() const { return G1CollectedHeap::InNeither; } - public: - void set_humongous(uintptr_t index) { - assert(get_by_index(index) != InCSet, "Should not overwrite InCSet values"); - set_by_index(index, G1CollectedHeap::IsHumongous); - } - - void clear_humongous(uintptr_t index) { - set_by_index(index, G1CollectedHeap::InNeither); - } - - void set_in_cset(uintptr_t index) { - assert(get_by_index(index) != G1CollectedHeap::IsHumongous, "Should not overwrite IsHumongous value"); - set_by_index(index, G1CollectedHeap::InCSet); - } - - bool is_in_cset_or_humongous(HeapWord* addr) const { return get_by_address(addr) != G1CollectedHeap::InNeither; } - bool is_in_cset(HeapWord* addr) const { return get_by_address(addr) == G1CollectedHeap::InCSet; } - G1CollectedHeap::in_cset_state_t at(HeapWord* addr) const { return (G1CollectedHeap::in_cset_state_t)get_by_address(addr); } - void clear() { G1BiasedMappedArray::clear(); } - }; - // This array is used for a quick test on whether a reference points into // the collection set or not. Each of the array's elements denotes whether the // corresponding region is in the collection set or not. - G1FastCSetBiasedMappedArray _in_cset_fast_test; + G1InCSetStateFastTestBiasedMappedArray _in_cset_fast_test; public: - inline in_cset_state_t in_cset_state(const oop obj); + inline InCSetState in_cset_state(const oop obj); // Return "TRUE" iff the given object address is in the reserved // region of g1. diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.inline.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.inline.hpp index 46c595da34f..ba1bf5f6bd9 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.inline.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.inline.hpp @@ -35,6 +35,41 @@ #include "runtime/orderAccess.inline.hpp" #include "utilities/taskqueue.hpp" +PLABStats* G1CollectedHeap::alloc_buffer_stats(InCSetState dest) { + switch (dest.value()) { + case InCSetState::Young: + return &_survivor_plab_stats; + case InCSetState::Old: + return &_old_plab_stats; + default: + ShouldNotReachHere(); + return NULL; // Keep some compilers happy + } +} + +size_t G1CollectedHeap::desired_plab_sz(InCSetState dest) { + size_t gclab_word_size = alloc_buffer_stats(dest)->desired_plab_sz(); + // Prevent humongous PLAB sizes for two reasons: + // * PLABs are allocated using a similar paths as oops, but should + // never be in a humongous region + // * Allowing humongous PLABs needlessly churns the region free lists + return MIN2(_humongous_object_threshold_in_words, gclab_word_size); +} + +HeapWord* G1CollectedHeap::par_allocate_during_gc(InCSetState dest, + size_t word_size, + AllocationContext_t context) { + switch (dest.value()) { + case InCSetState::Young: + return survivor_attempt_allocation(word_size, context); + case InCSetState::Old: + return old_attempt_allocation(word_size, context); + default: + ShouldNotReachHere(); + return NULL; // Keep some compilers happy + } +} + // Inline functions for G1CollectedHeap inline AllocationContextStats& G1CollectedHeap::allocation_context_stats() { @@ -203,7 +238,7 @@ bool G1CollectedHeap::is_in_cset_or_humongous(const oop obj) { return _in_cset_fast_test.is_in_cset_or_humongous((HeapWord*)obj); } -G1CollectedHeap::in_cset_state_t G1CollectedHeap::in_cset_state(const oop obj) { +InCSetState G1CollectedHeap::in_cset_state(const oop obj) { return _in_cset_fast_test.at((HeapWord*)obj); } diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp index d66e82d4dd6..5cc47a24964 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp @@ -1437,18 +1437,6 @@ bool G1CollectorPolicy::can_expand_young_list() { return young_list_length < young_list_max_length; } -uint G1CollectorPolicy::max_regions(int purpose) { - switch (purpose) { - case GCAllocForSurvived: - return _max_survivor_regions; - case GCAllocForTenured: - return REGIONS_UNLIMITED; - default: - ShouldNotReachHere(); - return REGIONS_UNLIMITED; - }; -} - void G1CollectorPolicy::update_max_gc_locker_expansion() { uint expansion_region_num = 0; if (GCLockerEdenExpansionPercent > 0) { @@ -1634,7 +1622,7 @@ void G1CollectorPolicy::add_old_region_to_cset(HeapRegion* hr) { hr->set_next_in_collection_set(_collection_set); _collection_set = hr; _collection_set_bytes_used_before += hr->used(); - _g1->register_region_with_in_cset_fast_test(hr); + _g1->register_old_region_with_in_cset_fast_test(hr); size_t rs_length = hr->rem_set()->occupied(); _recorded_rs_lengths += rs_length; _old_cset_region_length += 1; @@ -1767,7 +1755,7 @@ void G1CollectorPolicy::add_region_to_incremental_cset_common(HeapRegion* hr) { hr->set_in_collection_set(true); assert( hr->next_in_collection_set() == NULL, "invariant"); - _g1->register_region_with_in_cset_fast_test(hr); + _g1->register_young_region_with_in_cset_fast_test(hr); } // Add the region at the RHS of the incremental cset diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp index 3593be39cdb..a4236a0a369 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp @@ -881,28 +881,20 @@ private: public: uint tenuring_threshold() const { return _tenuring_threshold; } - inline GCAllocPurpose - evacuation_destination(HeapRegion* src_region, uint age, size_t word_sz) { - if (age < _tenuring_threshold && src_region->is_young()) { - return GCAllocForSurvived; - } else { - return GCAllocForTenured; - } - } - - inline bool track_object_age(GCAllocPurpose purpose) { - return purpose == GCAllocForSurvived; - } - static const uint REGIONS_UNLIMITED = (uint) -1; - uint max_regions(int purpose); - - // The limit on regions for a particular purpose is reached. - void note_alloc_region_limit_reached(int purpose) { - if (purpose == GCAllocForSurvived) { - _tenuring_threshold = 0; + uint max_regions(InCSetState dest) { + switch (dest.value()) { + case InCSetState::Young: + return _max_survivor_regions; + case InCSetState::Old: + return REGIONS_UNLIMITED; + default: + assert(false, err_msg("Unknown dest state: " CSETSTATE_FORMAT, dest.value())); + break; } + // keep some compilers happy + return 0; } void note_start_adding_survivor_regions() { diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1InCSetState.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1InCSetState.hpp new file mode 100644 index 00000000000..f13eaa0ae82 --- /dev/null +++ b/hotspot/src/share/vm/gc_implementation/g1/g1InCSetState.hpp @@ -0,0 +1,132 @@ +/* + * 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. + * + */ + +#ifndef SHARE_VM_GC_IMPLEMENTATION_G1_G1INCSETSTATE_HPP +#define SHARE_VM_GC_IMPLEMENTATION_G1_G1INCSETSTATE_HPP + +#include "gc_implementation/g1/g1BiasedArray.hpp" +#include "memory/allocation.hpp" + +// Per-region state during garbage collection. +struct InCSetState { + public: + // We use different types to represent the state value. Particularly SPARC puts + // values in structs from "left to right", i.e. MSB to LSB. This results in many + // unnecessary shift operations when loading and storing values of this type. + // This degrades performance significantly (>10%) on that platform. + // Other tested ABIs do not seem to have this problem, and actually tend to + // favor smaller types, so we use the smallest usable type there. +#ifdef SPARC + #define CSETSTATE_FORMAT INTPTR_FORMAT + typedef intptr_t in_cset_state_t; +#else + #define CSETSTATE_FORMAT "%d" + typedef int8_t in_cset_state_t; +#endif + private: + in_cset_state_t _value; + public: + enum { + // Selection of the values were driven to micro-optimize the encoding and + // frequency of the checks. + // The most common check is whether the region is in the collection set or not. + // This encoding allows us to use an != 0 check which in some architectures + // (x86*) can be encoded slightly more efficently than a normal comparison + // against zero. + // The same situation occurs when checking whether the region is humongous + // or not, which is encoded by values < 0. + // The other values are simply encoded in increasing generation order, which + // makes getting the next generation fast by a simple increment. + Humongous = -1, // The region is humongous - note that actually any value < 0 would be possible here. + NotInCSet = 0, // The region is not in the collection set. + Young = 1, // The region is in the collection set and a young region. + Old = 2, // The region is in the collection set and an old region. + Num + }; + + InCSetState(in_cset_state_t value = NotInCSet) : _value(value) { + assert(is_valid(), err_msg("Invalid state %d", _value)); + } + + in_cset_state_t value() const { return _value; } + + void set_old() { _value = Old; } + + bool is_in_cset_or_humongous() const { return _value != NotInCSet; } + bool is_in_cset() const { return _value > NotInCSet; } + bool is_humongous() const { return _value < NotInCSet; } + bool is_young() const { return _value == Young; } + bool is_old() const { return _value == Old; } + +#ifdef ASSERT + bool is_default() const { return !is_in_cset_or_humongous(); } + bool is_valid() const { return (_value >= Humongous) && (_value < Num); } + bool is_valid_gen() const { return (_value >= Young && _value <= Old); } +#endif +}; + +// Instances of this class are used for quick tests on whether a reference points +// into the collection set and into which generation or is a humongous object +// +// Each of the array's elements indicates whether the corresponding region is in +// the collection set and if so in which generation, or a humongous region. +// +// We use this to speed up reference processing during young collection and +// quickly reclaim humongous objects. For the latter, by making a humongous region +// succeed this test, we sort-of add it to the collection set. During the reference +// iteration closures, when we see a humongous region, we then simply mark it as +// referenced, i.e. live. +class G1InCSetStateFastTestBiasedMappedArray : public G1BiasedMappedArray { + protected: + InCSetState default_value() const { return InCSetState::NotInCSet; } + public: + void set_humongous(uintptr_t index) { + assert(get_by_index(index).is_default(), + err_msg("State at index " INTPTR_FORMAT" should be default but is " CSETSTATE_FORMAT, index, get_by_index(index).value())); + set_by_index(index, InCSetState::Humongous); + } + + void clear_humongous(uintptr_t index) { + set_by_index(index, InCSetState::NotInCSet); + } + + void set_in_young(uintptr_t index) { + assert(get_by_index(index).is_default(), + err_msg("State at index " INTPTR_FORMAT" should be default but is " CSETSTATE_FORMAT, index, get_by_index(index).value())); + set_by_index(index, InCSetState::Young); + } + + void set_in_old(uintptr_t index) { + assert(get_by_index(index).is_default(), + err_msg("State at index " INTPTR_FORMAT" should be default but is " CSETSTATE_FORMAT, index, get_by_index(index).value())); + set_by_index(index, InCSetState::Old); + } + + bool is_in_cset_or_humongous(HeapWord* addr) const { return at(addr).is_in_cset_or_humongous(); } + bool is_in_cset(HeapWord* addr) const { return at(addr).is_in_cset(); } + InCSetState at(HeapWord* addr) const { return get_by_address(addr); } + void clear() { G1BiasedMappedArray::clear(); } +}; + +#endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1INCSETSTATE_HPP diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.hpp index 79f8b52f682..4f6e655b511 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.hpp @@ -26,6 +26,7 @@ #define SHARE_VM_GC_IMPLEMENTATION_G1_G1OOPCLOSURES_HPP #include "memory/iterator.hpp" +#include "oops/markOop.hpp" class HeapRegion; class G1CollectedHeap; @@ -239,14 +240,14 @@ class G1UpdateRSOrPushRefOopClosure: public ExtendedOopClosure { G1CollectedHeap* _g1; G1RemSet* _g1_rem_set; HeapRegion* _from; - OopsInHeapRegionClosure* _push_ref_cl; + G1ParPushHeapRSClosure* _push_ref_cl; bool _record_refs_into_cset; uint _worker_i; public: G1UpdateRSOrPushRefOopClosure(G1CollectedHeap* g1h, G1RemSet* rs, - OopsInHeapRegionClosure* push_ref_cl, + G1ParPushHeapRSClosure* push_ref_cl, bool record_refs_into_cset, uint worker_i = 0); @@ -256,7 +257,8 @@ public: } bool self_forwarded(oop obj) { - bool result = (obj->is_forwarded() && (obj->forwardee()== obj)); + markOop m = obj->mark(); + bool result = (m->is_marked() && ((oop)m->decode_pointer() == obj)); return result; } diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.inline.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.inline.hpp index ecdb19440fa..6afda16da20 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.inline.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.inline.hpp @@ -67,8 +67,8 @@ inline void G1ParScanClosure::do_oop_nv(T* p) { if (!oopDesc::is_null(heap_oop)) { oop obj = oopDesc::decode_heap_oop_not_null(heap_oop); - G1CollectedHeap::in_cset_state_t state = _g1->in_cset_state(obj); - if (state == G1CollectedHeap::InCSet) { + const InCSetState state = _g1->in_cset_state(obj); + if (state.is_in_cset()) { // We're not going to even bother checking whether the object is // already forwarded or not, as this usually causes an immediate // stall. We'll try to prefetch the object (for write, given that @@ -87,7 +87,7 @@ inline void G1ParScanClosure::do_oop_nv(T* p) { _par_scan_state->push_on_queue(p); } else { - if (state == G1CollectedHeap::IsHumongous) { + if (state.is_humongous()) { _g1->set_humongous_is_live(obj); } _par_scan_state->update_rs(_from, p, _worker_id); diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1PageBasedVirtualSpace.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1PageBasedVirtualSpace.cpp index 1b294edffed..d972b5cc71c 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1PageBasedVirtualSpace.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1PageBasedVirtualSpace.cpp @@ -131,6 +131,9 @@ MemRegion G1PageBasedVirtualSpace::commit(uintptr_t start, size_t size_in_pages) _committed.set_range(start, start + size_in_pages); MemRegion result((HeapWord*)page_start(start), byte_size_for_pages(size_in_pages) / HeapWordSize); + if (AlwaysPreTouch) { + os::pretouch_memory((char*)result.start(), (char*)result.end()); + } return result; } diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1ParScanThreadState.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1ParScanThreadState.cpp index adfa805f1cd..8849d42dd78 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1ParScanThreadState.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1ParScanThreadState.cpp @@ -38,6 +38,7 @@ G1ParScanThreadState::G1ParScanThreadState(G1CollectedHeap* g1h, uint queue_num, _g1_rem(g1h->g1_rem_set()), _hash_seed(17), _queue_num(queue_num), _term_attempts(0), + _tenuring_threshold(g1h->g1_policy()->tenuring_threshold()), _age_table(false), _scanner(g1h, rp), _strong_roots_time(0), _term_time(0) { _scanner.set_par_scan_thread_state(this); @@ -59,6 +60,12 @@ G1ParScanThreadState::G1ParScanThreadState(G1CollectedHeap* g1h, uint queue_num, _g1_par_allocator = G1ParGCAllocator::create_allocator(_g1h); + _dest[InCSetState::NotInCSet] = InCSetState::NotInCSet; + // The dest for Young is used when the objects are aged enough to + // need to be moved to the next space. + _dest[InCSetState::Young] = InCSetState::Old; + _dest[InCSetState::Old] = InCSetState::Old; + _start = os::elapsedTime(); } @@ -150,52 +157,94 @@ void G1ParScanThreadState::trim_queue() { } while (!_refs->is_empty()); } -oop G1ParScanThreadState::copy_to_survivor_space(oop const old, +HeapWord* G1ParScanThreadState::allocate_in_next_plab(InCSetState const state, + InCSetState* dest, + size_t word_sz, + AllocationContext_t const context) { + assert(state.is_in_cset_or_humongous(), err_msg("Unexpected state: " CSETSTATE_FORMAT, state.value())); + assert(dest->is_in_cset_or_humongous(), err_msg("Unexpected dest: " CSETSTATE_FORMAT, dest->value())); + + // Right now we only have two types of regions (young / old) so + // let's keep the logic here simple. We can generalize it when necessary. + if (dest->is_young()) { + HeapWord* const obj_ptr = _g1_par_allocator->allocate(InCSetState::Old, + word_sz, context); + if (obj_ptr == NULL) { + return NULL; + } + // Make sure that we won't attempt to copy any other objects out + // of a survivor region (given that apparently we cannot allocate + // any new ones) to avoid coming into this slow path. + _tenuring_threshold = 0; + dest->set_old(); + return obj_ptr; + } else { + assert(dest->is_old(), err_msg("Unexpected dest: " CSETSTATE_FORMAT, dest->value())); + // no other space to try. + return NULL; + } +} + +InCSetState G1ParScanThreadState::next_state(InCSetState const state, markOop const m, uint& age) { + if (state.is_young()) { + age = !m->has_displaced_mark_helper() ? m->age() + : m->displaced_mark_helper()->age(); + if (age < _tenuring_threshold) { + return state; + } + } + return dest(state); +} + +oop G1ParScanThreadState::copy_to_survivor_space(InCSetState const state, + oop const old, markOop const old_mark) { - size_t word_sz = old->size(); - HeapRegion* from_region = _g1h->heap_region_containing_raw(old); + const size_t word_sz = old->size(); + HeapRegion* const from_region = _g1h->heap_region_containing_raw(old); // +1 to make the -1 indexes valid... - int young_index = from_region->young_index_in_cset()+1; + const int young_index = from_region->young_index_in_cset()+1; assert( (from_region->is_young() && young_index > 0) || (!from_region->is_young() && young_index == 0), "invariant" ); - G1CollectorPolicy* g1p = _g1h->g1_policy(); - uint age = old_mark->has_displaced_mark_helper() ? old_mark->displaced_mark_helper()->age() - : old_mark->age(); - GCAllocPurpose alloc_purpose = g1p->evacuation_destination(from_region, age, - word_sz); - AllocationContext_t context = from_region->allocation_context(); - HeapWord* obj_ptr = _g1_par_allocator->allocate(alloc_purpose, word_sz, context); + const AllocationContext_t context = from_region->allocation_context(); + + uint age = 0; + InCSetState dest_state = next_state(state, old_mark, age); + HeapWord* obj_ptr = _g1_par_allocator->plab_allocate(dest_state, word_sz, context); + + // PLAB allocations should succeed most of the time, so we'll + // normally check against NULL once and that's it. + if (obj_ptr == NULL) { + obj_ptr = _g1_par_allocator->allocate_direct_or_new_plab(dest_state, word_sz, context); + if (obj_ptr == NULL) { + obj_ptr = allocate_in_next_plab(state, &dest_state, word_sz, context); + if (obj_ptr == NULL) { + // This will either forward-to-self, or detect that someone else has + // installed a forwarding pointer. + return _g1h->handle_evacuation_failure_par(this, old); + } + } + } + + assert(obj_ptr != NULL, "when we get here, allocation should have succeeded"); #ifndef PRODUCT // Should this evacuation fail? if (_g1h->evacuation_should_fail()) { - if (obj_ptr != NULL) { - _g1_par_allocator->undo_allocation(alloc_purpose, obj_ptr, word_sz, context); - obj_ptr = NULL; - } - } -#endif // !PRODUCT - - if (obj_ptr == NULL) { - // This will either forward-to-self, or detect that someone else has - // installed a forwarding pointer. + // Doing this after all the allocation attempts also tests the + // undo_allocation() method too. + _g1_par_allocator->undo_allocation(dest_state, obj_ptr, word_sz, context); return _g1h->handle_evacuation_failure_par(this, old); } - - oop obj = oop(obj_ptr); +#endif // !PRODUCT // We're going to allocate linearly, so might as well prefetch ahead. Prefetch::write(obj_ptr, PrefetchCopyIntervalInBytes); - oop forward_ptr = old->forward_to_atomic(obj); + const oop obj = oop(obj_ptr); + const oop forward_ptr = old->forward_to_atomic(obj); if (forward_ptr == NULL) { Copy::aligned_disjoint_words((HeapWord*) old, obj_ptr, word_sz); - // alloc_purpose is just a hint to allocate() above, recheck the type of region - // we actually allocated from and update alloc_purpose accordingly - HeapRegion* to_region = _g1h->heap_region_containing_raw(obj_ptr); - alloc_purpose = to_region->is_young() ? GCAllocForSurvived : GCAllocForTenured; - - if (g1p->track_object_age(alloc_purpose)) { + if (dest_state.is_young()) { if (age < markOopDesc::max_age) { age++; } @@ -215,13 +264,19 @@ oop G1ParScanThreadState::copy_to_survivor_space(oop const old, } if (G1StringDedup::is_enabled()) { - G1StringDedup::enqueue_from_evacuation(from_region->is_young(), - to_region->is_young(), + const bool is_from_young = state.is_young(); + const bool is_to_young = dest_state.is_young(); + assert(is_from_young == _g1h->heap_region_containing_raw(old)->is_young(), + "sanity"); + assert(is_to_young == _g1h->heap_region_containing_raw(obj)->is_young(), + "sanity"); + G1StringDedup::enqueue_from_evacuation(is_from_young, + is_to_young, queue_num(), obj); } - size_t* surv_young_words = surviving_young_words(); + size_t* const surv_young_words = surviving_young_words(); surv_young_words[young_index] += word_sz; if (obj->is_objArray() && arrayOop(obj)->length() >= ParGCArrayScanChunk) { @@ -232,14 +287,13 @@ oop G1ParScanThreadState::copy_to_survivor_space(oop const old, oop* old_p = set_partial_array_mask(old); push_on_queue(old_p); } else { - // No point in using the slower heap_region_containing() method, - // given that we know obj is in the heap. - _scanner.set_region(_g1h->heap_region_containing_raw(obj)); + HeapRegion* const to_region = _g1h->heap_region_containing_raw(obj_ptr); + _scanner.set_region(to_region); obj->oop_iterate_backwards(&_scanner); } + return obj; } else { - _g1_par_allocator->undo_allocation(alloc_purpose, obj_ptr, word_sz, context); - obj = forward_ptr; + _g1_par_allocator->undo_allocation(dest_state, obj_ptr, word_sz, context); + return forward_ptr; } - return obj; } diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1ParScanThreadState.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1ParScanThreadState.hpp index a7c2f8ea119..0b69122e606 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1ParScanThreadState.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1ParScanThreadState.hpp @@ -46,14 +46,16 @@ class G1ParScanThreadState : public StackObj { G1SATBCardTableModRefBS* _ct_bs; G1RemSet* _g1_rem; - G1ParGCAllocator* _g1_par_allocator; + G1ParGCAllocator* _g1_par_allocator; - ageTable _age_table; + ageTable _age_table; + InCSetState _dest[InCSetState::Num]; + // Local tenuring threshold. + uint _tenuring_threshold; + G1ParScanClosure _scanner; - G1ParScanClosure _scanner; - - size_t _alloc_buffer_waste; - size_t _undo_waste; + size_t _alloc_buffer_waste; + size_t _undo_waste; OopsInHeapRegionClosure* _evac_failure_cl; @@ -82,6 +84,14 @@ class G1ParScanThreadState : public StackObj { DirtyCardQueue& dirty_card_queue() { return _dcq; } G1SATBCardTableModRefBS* ctbs() { return _ct_bs; } + InCSetState dest(InCSetState original) const { + assert(original.is_valid(), + err_msg("Original state invalid: " CSETSTATE_FORMAT, original.value())); + assert(_dest[original.value()].is_valid_gen(), + err_msg("Dest state is invalid: " CSETSTATE_FORMAT, _dest[original.value()].value())); + return _dest[original.value()]; + } + public: G1ParScanThreadState(G1CollectedHeap* g1h, uint queue_num, ReferenceProcessor* rp); ~G1ParScanThreadState(); @@ -112,7 +122,6 @@ class G1ParScanThreadState : public StackObj { } } } - public: void set_evac_failure_closure(OopsInHeapRegionClosure* evac_failure_cl) { _evac_failure_cl = evac_failure_cl; @@ -193,9 +202,20 @@ class G1ParScanThreadState : public StackObj { template inline void deal_with_reference(T* ref_to_scan); inline void dispatch_reference(StarTask ref); + + // Tries to allocate word_sz in the PLAB of the next "generation" after trying to + // allocate into dest. State is the original (source) cset state for the object + // that is allocated for. + // Returns a non-NULL pointer if successful, and updates dest if required. + HeapWord* allocate_in_next_plab(InCSetState const state, + InCSetState* dest, + size_t word_sz, + AllocationContext_t const context); + + inline InCSetState next_state(InCSetState const state, markOop const m, uint& age); public: - oop copy_to_survivor_space(oop const obj, markOop const old_mark); + oop copy_to_survivor_space(InCSetState const state, oop const obj, markOop const old_mark); void trim_queue(); diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1ParScanThreadState.inline.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1ParScanThreadState.inline.hpp index 8e20df6fe66..1b03f8caae2 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1ParScanThreadState.inline.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1ParScanThreadState.inline.hpp @@ -38,21 +38,21 @@ template void G1ParScanThreadState::do_oop_evac(T* p, HeapRegion* from // set, due to (benign) races in the claim mechanism during RSet scanning more // than one thread might claim the same card. So the same card may be // processed multiple times. So redo this check. - G1CollectedHeap::in_cset_state_t in_cset_state = _g1h->in_cset_state(obj); - if (in_cset_state == G1CollectedHeap::InCSet) { + const InCSetState in_cset_state = _g1h->in_cset_state(obj); + if (in_cset_state.is_in_cset()) { oop forwardee; markOop m = obj->mark(); if (m->is_marked()) { forwardee = (oop) m->decode_pointer(); } else { - forwardee = copy_to_survivor_space(obj, m); + forwardee = copy_to_survivor_space(in_cset_state, obj, m); } oopDesc::encode_store_heap_oop(p, forwardee); - } else if (in_cset_state == G1CollectedHeap::IsHumongous) { + } else if (in_cset_state.is_humongous()) { _g1h->set_humongous_is_live(obj); } else { - assert(in_cset_state == G1CollectedHeap::InNeither, - err_msg("In_cset_state must be InNeither here, but is %d", in_cset_state)); + assert(!in_cset_state.is_in_cset_or_humongous(), + err_msg("In_cset_state must be NotInCSet here, but is " CSETSTATE_FORMAT, in_cset_state.value())); } assert(obj != NULL, "Must be"); diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp index 78445eee741..010a8dd7b80 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp @@ -80,7 +80,7 @@ G1RemSet::G1RemSet(G1CollectedHeap* g1, CardTableModRefBS* ct_bs) _prev_period_summary() { _seq_task = new SubTasksDone(NumSeqTasks); - _cset_rs_update_cl = NEW_C_HEAP_ARRAY(OopsInHeapRegionClosure*, n_workers(), mtGC); + _cset_rs_update_cl = NEW_C_HEAP_ARRAY(G1ParPushHeapRSClosure*, n_workers(), mtGC); for (uint i = 0; i < n_workers(); i++) { _cset_rs_update_cl[i] = NULL; } @@ -94,14 +94,14 @@ G1RemSet::~G1RemSet() { for (uint i = 0; i < n_workers(); i++) { assert(_cset_rs_update_cl[i] == NULL, "it should be"); } - FREE_C_HEAP_ARRAY(OopsInHeapRegionClosure*, _cset_rs_update_cl); + FREE_C_HEAP_ARRAY(G1ParPushHeapRSClosure*, _cset_rs_update_cl); } class ScanRSClosure : public HeapRegionClosure { size_t _cards_done, _cards; G1CollectedHeap* _g1h; - OopsInHeapRegionClosure* _oc; + G1ParPushHeapRSClosure* _oc; CodeBlobClosure* _code_root_cl; G1BlockOffsetSharedArray* _bot_shared; @@ -113,7 +113,7 @@ class ScanRSClosure : public HeapRegionClosure { bool _try_claimed; public: - ScanRSClosure(OopsInHeapRegionClosure* oc, + ScanRSClosure(G1ParPushHeapRSClosure* oc, CodeBlobClosure* code_root_cl, uint worker_i) : _oc(oc), @@ -135,8 +135,7 @@ public: void scanCard(size_t index, HeapRegion *r) { // Stack allocate the DirtyCardToOopClosure instance HeapRegionDCTOC cl(_g1h, r, _oc, - CardTableModRefBS::Precise, - HeapRegionDCTOC::IntoCSFilterKind); + CardTableModRefBS::Precise); // Set the "from" region in the closure. _oc->set_region(r); @@ -231,7 +230,7 @@ public: size_t cards_looked_up() { return _cards;} }; -void G1RemSet::scanRS(OopsInHeapRegionClosure* oc, +void G1RemSet::scanRS(G1ParPushHeapRSClosure* oc, CodeBlobClosure* code_root_cl, uint worker_i) { double rs_time_start = os::elapsedTime(); @@ -301,7 +300,7 @@ void G1RemSet::cleanupHRRS() { HeapRegionRemSet::cleanup(); } -void G1RemSet::oops_into_collection_set_do(OopsInHeapRegionClosure* oc, +void G1RemSet::oops_into_collection_set_do(G1ParPushHeapRSClosure* oc, CodeBlobClosure* code_root_cl, uint worker_i) { #if CARD_REPEAT_HISTO @@ -417,7 +416,7 @@ G1Mux2Closure::G1Mux2Closure(OopClosure *c1, OopClosure *c2) : G1UpdateRSOrPushRefOopClosure:: G1UpdateRSOrPushRefOopClosure(G1CollectedHeap* g1h, G1RemSet* rs, - OopsInHeapRegionClosure* push_ref_cl, + G1ParPushHeapRSClosure* push_ref_cl, bool record_refs_into_cset, uint worker_i) : _g1(g1h), _g1_rem_set(rs), _from(NULL), @@ -518,7 +517,7 @@ bool G1RemSet::refine_card(jbyte* card_ptr, uint worker_i, ct_freq_note_card(_ct_bs->index_for(start)); #endif - OopsInHeapRegionClosure* oops_in_heap_closure = NULL; + G1ParPushHeapRSClosure* oops_in_heap_closure = NULL; if (check_for_refs_into_cset) { // ConcurrentG1RefineThreads have worker numbers larger than what // _cset_rs_update_cl[] is set up to handle. But those threads should diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.hpp index ae51cdd19ce..468d109803b 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.hpp @@ -33,6 +33,7 @@ class G1CollectedHeap; class CardTableModRefBarrierSet; class ConcurrentG1Refine; +class G1ParPushHeapRSClosure; // A G1RemSet in which each heap region has a rem set that records the // external heap references into it. Uses a mod ref bs to track updates, @@ -68,7 +69,7 @@ protected: // Used for caching the closure that is responsible for scanning // references into the collection set. - OopsInHeapRegionClosure** _cset_rs_update_cl; + G1ParPushHeapRSClosure** _cset_rs_update_cl; // Print the given summary info virtual void print_summary_info(G1RemSetSummary * summary, const char * header = NULL); @@ -95,7 +96,7 @@ public: // partitioning the work to be done. It should be the same as // the "i" passed to the calling thread's work(i) function. // In the sequential case this param will be ignored. - void oops_into_collection_set_do(OopsInHeapRegionClosure* blk, + void oops_into_collection_set_do(G1ParPushHeapRSClosure* blk, CodeBlobClosure* code_root_cl, uint worker_i); @@ -107,7 +108,7 @@ public: void prepare_for_oops_into_collection_set_do(); void cleanup_after_oops_into_collection_set_do(); - void scanRS(OopsInHeapRegionClosure* oc, + void scanRS(G1ParPushHeapRSClosure* oc, CodeBlobClosure* code_root_cl, uint worker_i); diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1SATBCardTableModRefBS.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1SATBCardTableModRefBS.cpp index 1e3788858b0..c6a1aef2420 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1SATBCardTableModRefBS.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1SATBCardTableModRefBS.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 @@ -33,7 +33,7 @@ #include "runtime/thread.inline.hpp" G1SATBCardTableModRefBS::G1SATBCardTableModRefBS(MemRegion whole_heap) : - CardTableModRefBSForCTRS(whole_heap) + CardTableModRefBS(whole_heap) { _kind = G1SATBCT; } diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1SATBCardTableModRefBS.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1SATBCardTableModRefBS.hpp index 6a06523d0cb..c4d9318b071 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1SATBCardTableModRefBS.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1SATBCardTableModRefBS.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 @@ -37,7 +37,7 @@ class G1SATBCardTableLoggingModRefBS; // This barrier is specialized to use a logging barrier to support // snapshot-at-the-beginning marking. -class G1SATBCardTableModRefBS: public CardTableModRefBSForCTRS { +class G1SATBCardTableModRefBS: public CardTableModRefBS { protected: enum G1CardValues { g1_young_gen = CT_MR_BS_last_reserved << 1 diff --git a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp index 7be4de130d2..5ead54b16a5 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp @@ -48,93 +48,55 @@ size_t HeapRegion::GrainWords = 0; size_t HeapRegion::CardsPerRegion = 0; HeapRegionDCTOC::HeapRegionDCTOC(G1CollectedHeap* g1, - HeapRegion* hr, ExtendedOopClosure* cl, - CardTableModRefBS::PrecisionStyle precision, - FilterKind fk) : + HeapRegion* hr, + G1ParPushHeapRSClosure* cl, + CardTableModRefBS::PrecisionStyle precision) : DirtyCardToOopClosure(hr, cl, precision, NULL), - _hr(hr), _fk(fk), _g1(g1) { } + _hr(hr), _rs_scan(cl), _g1(g1) { } FilterOutOfRegionClosure::FilterOutOfRegionClosure(HeapRegion* r, OopClosure* oc) : _r_bottom(r->bottom()), _r_end(r->end()), _oc(oc) { } -template -HeapWord* walk_mem_region_loop(ClosureType* cl, G1CollectedHeap* g1h, - HeapRegion* hr, - HeapWord* cur, HeapWord* top) { - oop cur_oop = oop(cur); - size_t oop_size = hr->block_size(cur); - HeapWord* next_obj = cur + oop_size; - while (next_obj < top) { - // Keep filtering the remembered set. - if (!g1h->is_obj_dead(cur_oop, hr)) { - // Bottom lies entirely below top, so we can call the - // non-memRegion version of oop_iterate below. - cur_oop->oop_iterate(cl); - } - cur = next_obj; - cur_oop = oop(cur); - oop_size = hr->block_size(cur); - next_obj = cur + oop_size; - } - return cur; -} - void HeapRegionDCTOC::walk_mem_region(MemRegion mr, HeapWord* bottom, HeapWord* top) { G1CollectedHeap* g1h = _g1; size_t oop_size; - ExtendedOopClosure* cl2 = NULL; - - FilterIntoCSClosure intoCSFilt(this, g1h, _cl); - FilterOutOfRegionClosure outOfRegionFilt(_hr, _cl); - - switch (_fk) { - case NoFilterKind: cl2 = _cl; break; - case IntoCSFilterKind: cl2 = &intoCSFilt; break; - case OutOfRegionFilterKind: cl2 = &outOfRegionFilt; break; - default: ShouldNotReachHere(); - } + HeapWord* cur = bottom; // Start filtering what we add to the remembered set. If the object is // not considered dead, either because it is marked (in the mark bitmap) // or it was allocated after marking finished, then we add it. Otherwise // we can safely ignore the object. - if (!g1h->is_obj_dead(oop(bottom), _hr)) { - oop_size = oop(bottom)->oop_iterate(cl2, mr); + if (!g1h->is_obj_dead(oop(cur), _hr)) { + oop_size = oop(cur)->oop_iterate(_rs_scan, mr); } else { - oop_size = _hr->block_size(bottom); + oop_size = _hr->block_size(cur); } - bottom += oop_size; + cur += oop_size; - if (bottom < top) { - // We replicate the loop below for several kinds of possible filters. - switch (_fk) { - case NoFilterKind: - bottom = walk_mem_region_loop(_cl, g1h, _hr, bottom, top); - break; - - case IntoCSFilterKind: { - FilterIntoCSClosure filt(this, g1h, _cl); - bottom = walk_mem_region_loop(&filt, g1h, _hr, bottom, top); - break; - } - - case OutOfRegionFilterKind: { - FilterOutOfRegionClosure filt(_hr, _cl); - bottom = walk_mem_region_loop(&filt, g1h, _hr, bottom, top); - break; - } - - default: - ShouldNotReachHere(); + if (cur < top) { + oop cur_oop = oop(cur); + oop_size = _hr->block_size(cur); + HeapWord* next_obj = cur + oop_size; + while (next_obj < top) { + // Keep filtering the remembered set. + if (!g1h->is_obj_dead(cur_oop, _hr)) { + // Bottom lies entirely below top, so we can call the + // non-memRegion version of oop_iterate below. + cur_oop->oop_iterate(_rs_scan); + } + cur = next_obj; + cur_oop = oop(cur); + oop_size = _hr->block_size(cur); + next_obj = cur + oop_size; } // Last object. Need to do dead-obj filtering here too. - if (!g1h->is_obj_dead(oop(bottom), _hr)) { - oop(bottom)->oop_iterate(cl2, mr); + if (!g1h->is_obj_dead(oop(cur), _hr)) { + oop(cur)->oop_iterate(_rs_scan, mr); } } } diff --git a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp index 3c4e91b0cf8..e7342cdacf4 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp @@ -67,17 +67,9 @@ class nmethod; // sets. class HeapRegionDCTOC : public DirtyCardToOopClosure { -public: - // Specification of possible DirtyCardToOopClosure filtering. - enum FilterKind { - NoFilterKind, - IntoCSFilterKind, - OutOfRegionFilterKind - }; - -protected: +private: HeapRegion* _hr; - FilterKind _fk; + G1ParPushHeapRSClosure* _rs_scan; G1CollectedHeap* _g1; // Walk the given memory region from bottom to (actual) top @@ -90,9 +82,9 @@ protected: public: HeapRegionDCTOC(G1CollectedHeap* g1, - HeapRegion* hr, ExtendedOopClosure* cl, - CardTableModRefBS::PrecisionStyle precision, - FilterKind fk); + HeapRegion* hr, + G1ParPushHeapRSClosure* cl, + CardTableModRefBS::PrecisionStyle precision); }; // The complicating factor is that BlockOffsetTable diverged diff --git a/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp b/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp index 058426f4603..9551aed3022 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp @@ -407,20 +407,8 @@ void FromCardCache::clear(uint region_idx) { } } -void OtherRegionsTable::initialize(uint max_regions) { - FromCardCache::initialize(HeapRegionRemSet::num_par_rem_sets(), max_regions); -} - -void OtherRegionsTable::invalidate(uint start_idx, size_t num_regions) { - FromCardCache::invalidate(start_idx, num_regions); -} - -void OtherRegionsTable::print_from_card_cache() { - FromCardCache::print(); -} - void OtherRegionsTable::add_reference(OopOrNarrowOopStar from, uint tid) { - uint cur_hrm_ind = hr()->hrm_index(); + uint cur_hrm_ind = _hr->hrm_index(); if (G1TraceHeapRegionRememberedSet) { gclog_or_tty->print_cr("ORT::add_reference_work(" PTR_FORMAT "->" PTR_FORMAT ").", @@ -434,7 +422,7 @@ void OtherRegionsTable::add_reference(OopOrNarrowOopStar from, uint tid) { if (G1TraceHeapRegionRememberedSet) { gclog_or_tty->print_cr("Table for [" PTR_FORMAT "...): card %d (cache = %d)", - hr()->bottom(), from_card, + _hr->bottom(), from_card, FromCardCache::at(tid, cur_hrm_ind)); } @@ -477,13 +465,13 @@ void OtherRegionsTable::add_reference(OopOrNarrowOopStar from, uint tid) { if (G1HRRSUseSparseTable && _sparse_table.add_card(from_hrm_ind, card_index)) { if (G1RecordHRRSOops) { - HeapRegionRemSet::record(hr(), from); + HeapRegionRemSet::record(_hr, from); if (G1TraceHeapRegionRememberedSet) { gclog_or_tty->print(" Added card " PTR_FORMAT " to region " "[" PTR_FORMAT "...) for ref " PTR_FORMAT ".\n", align_size_down(uintptr_t(from), CardTableModRefBS::card_size), - hr()->bottom(), from); + _hr->bottom(), from); } } if (G1TraceHeapRegionRememberedSet) { @@ -539,13 +527,13 @@ void OtherRegionsTable::add_reference(OopOrNarrowOopStar from, uint tid) { prt->add_reference(from); if (G1RecordHRRSOops) { - HeapRegionRemSet::record(hr(), from); + HeapRegionRemSet::record(_hr, from); if (G1TraceHeapRegionRememberedSet) { gclog_or_tty->print("Added card " PTR_FORMAT " to region " "[" PTR_FORMAT "...) for ref " PTR_FORMAT ".\n", align_size_down(uintptr_t(from), CardTableModRefBS::card_size), - hr()->bottom(), from); + _hr->bottom(), from); } } assert(contains_reference(from), "We just added it!"); @@ -614,7 +602,7 @@ PerRegionTable* OtherRegionsTable::delete_region_table() { if (G1TraceHeapRegionRememberedSet) { gclog_or_tty->print("Coarsened entry in region [" PTR_FORMAT "...] " "for region [" PTR_FORMAT "...] (" SIZE_FORMAT " coarse entries).\n", - hr()->bottom(), + _hr->bottom(), max->hr()->bottom(), _n_coarse_entries); } @@ -627,13 +615,11 @@ PerRegionTable* OtherRegionsTable::delete_region_table() { return max; } - -// At present, this must be called stop-world single-threaded. void OtherRegionsTable::scrub(CardTableModRefBS* ctbs, BitMap* region_bm, BitMap* card_bm) { // First eliminated garbage regions from the coarse map. if (G1RSScrubVerbose) { - gclog_or_tty->print_cr("Scrubbing region %u:", hr()->hrm_index()); + gclog_or_tty->print_cr("Scrubbing region %u:", _hr->hrm_index()); } assert(_coarse_map.size() == region_bm->size(), "Precondition"); @@ -752,7 +738,7 @@ size_t OtherRegionsTable::fl_mem_size() { } void OtherRegionsTable::clear_fcc() { - FromCardCache::clear(hr()->hrm_index()); + FromCardCache::clear(_hr->hrm_index()); } void OtherRegionsTable::clear() { @@ -774,27 +760,6 @@ void OtherRegionsTable::clear() { clear_fcc(); } -bool OtherRegionsTable::del_single_region_table(size_t ind, - HeapRegion* hr) { - assert(0 <= ind && ind < _max_fine_entries, "Preconditions."); - PerRegionTable** prev_addr = &_fine_grain_regions[ind]; - PerRegionTable* prt = *prev_addr; - while (prt != NULL && prt->hr() != hr) { - prev_addr = prt->collision_list_next_addr(); - prt = prt->collision_list_next(); - } - if (prt != NULL) { - assert(prt->hr() == hr, "Loop postcondition."); - *prev_addr = prt->collision_list_next(); - unlink_from_all(prt); - PerRegionTable::free(prt); - _n_fine_entries--; - return true; - } else { - return false; - } -} - bool OtherRegionsTable::contains_reference(OopOrNarrowOopStar from) const { // Cast away const in this case. MutexLockerEx x((Mutex*)_m, Mutex::_no_safepoint_check_flag); @@ -840,7 +805,7 @@ uint HeapRegionRemSet::num_par_rem_sets() { HeapRegionRemSet::HeapRegionRemSet(G1BlockOffsetSharedArray* bosa, HeapRegion* hr) : _bosa(bosa), - _m(Mutex::leaf, FormatBuffer<128>("HeapRegionRemSet lock #%u", hr->hrm_index()), true), + _m(Mutex::leaf, FormatBuffer<128>("HeapRegionRemSet lock #%u", hr->hrm_index()), true, Monitor::_safepoint_check_never), _code_roots(), _other_regions(hr, &_m), _iter_state(Unclaimed), _iter_claimed(0) { reset_for_par_iteration(); } @@ -975,7 +940,7 @@ HeapRegionRemSetIterator:: HeapRegionRemSetIterator(HeapRegionRemSet* hrrs) : _hrrs(hrrs), _g1h(G1CollectedHeap::heap()), _coarse_map(&hrrs->_other_regions._coarse_map), - _bosa(hrrs->bosa()), + _bosa(hrrs->_bosa), _is(Sparse), // Set these values so that we increment to the first region. _coarse_cur_region_index(-1), diff --git a/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.hpp b/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.hpp index d55fe1858df..bfff90abaef 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.hpp @@ -162,32 +162,36 @@ class OtherRegionsTable VALUE_OBJ_CLASS_SPEC { // to hold _m, and the fine-grain table to be full. PerRegionTable* delete_region_table(); - // If a PRT for "hr" is in the bucket list indicated by "ind" (which must - // be the correct index for "hr"), delete it and return true; else return - // false. - bool del_single_region_table(size_t ind, HeapRegion* hr); - // link/add the given fine grain remembered set into the "all" list void link_to_all(PerRegionTable * prt); // unlink/remove the given fine grain remembered set into the "all" list void unlink_from_all(PerRegionTable * prt); -public: - OtherRegionsTable(HeapRegion* hr, Mutex* m); + bool contains_reference_locked(OopOrNarrowOopStar from) const; - HeapRegion* hr() const { return _hr; } + // Clear the from_card_cache entries for this region. + void clear_fcc(); +public: + // Create a new remembered set for the given heap region. The given mutex should + // be used to ensure consistency. + OtherRegionsTable(HeapRegion* hr, Mutex* m); // For now. Could "expand" some tables in the future, so that this made // sense. void add_reference(OopOrNarrowOopStar from, uint tid); + // Returns whether the remembered set contains the given reference. + bool contains_reference(OopOrNarrowOopStar from) const; + // Removes any entries shown by the given bitmaps to contain only dead - // objects. + // objects. Not thread safe. + // Set bits in the bitmaps indicate that the given region or card is live. void scrub(CardTableModRefBS* ctbs, BitMap* region_bm, BitMap* card_bm); - // Returns whether this remembered set (and all sub-sets) contain no entries. + // Returns whether this remembered set (and all sub-sets) does not contain any entry. bool is_empty() const; + // Returns the number of cards contained in this remembered set. size_t occupied() const; size_t occ_fine() const; size_t occ_coarse() const; @@ -195,31 +199,17 @@ public: static jint n_coarsenings() { return _n_coarsenings; } - // Returns size in bytes. - // Not const because it takes a lock. + // Returns size of the actual remembered set containers in bytes. size_t mem_size() const; + // Returns the size of static data in bytes. static size_t static_mem_size(); + // Returns the size of the free list content in bytes. static size_t fl_mem_size(); - bool contains_reference(OopOrNarrowOopStar from) const; - bool contains_reference_locked(OopOrNarrowOopStar from) const; - + // Clear the entire contents of this remembered set. void clear(); - // Specifically clear the from_card_cache. - void clear_fcc(); - void do_cleanup_work(HRRSCleanupTask* hrrs_cleanup_task); - - // Declare the heap size (in # of regions) to the OtherRegionsTable. - // (Uses it to initialize from_card_cache). - static void initialize(uint max_regions); - - // Declares that regions between start_idx <= i < start_idx + num_regions are - // not in use. Make sure that any entries for these regions are invalid. - static void invalidate(uint start_idx, size_t num_regions); - - static void print_from_card_cache(); }; class HeapRegionRemSet : public CHeapObj { @@ -233,7 +223,6 @@ public: private: G1BlockOffsetSharedArray* _bosa; - G1BlockOffsetSharedArray* bosa() const { return _bosa; } // A set of code blobs (nmethods) whose code contains pointers into // the region that owns this RSet. @@ -268,10 +257,6 @@ public: static uint num_par_rem_sets(); static void setup_remset_size(); - HeapRegion* hr() const { - return _other_regions.hr(); - } - bool is_empty() const { return (strong_code_roots_list_length() == 0) && _other_regions.is_empty(); } @@ -305,8 +290,9 @@ public: _other_regions.add_reference(from, tid); } - // Removes any entries shown by the given bitmaps to contain only dead - // objects. + // Removes any entries in the remembered set shown by the given bitmaps to + // contain only dead objects. Not thread safe. + // One bits in the bitmaps indicate that the given region or card is live. void scrub(CardTableModRefBS* ctbs, BitMap* region_bm, BitMap* card_bm); // The region is being reclaimed; clear its remset, and any mention of @@ -397,16 +383,16 @@ public: // Declare the heap size (in # of regions) to the HeapRegionRemSet(s). // (Uses it to initialize from_card_cache). static void init_heap(uint max_regions) { - OtherRegionsTable::initialize(max_regions); + FromCardCache::initialize(num_par_rem_sets(), max_regions); } - static void invalidate(uint start_idx, uint num_regions) { - OtherRegionsTable::invalidate(start_idx, num_regions); + static void invalidate_from_card_cache(uint start_idx, size_t num_regions) { + FromCardCache::invalidate(start_idx, num_regions); } #ifndef PRODUCT static void print_from_card_cache() { - OtherRegionsTable::print_from_card_cache(); + FromCardCache::print(); } #endif diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/gcTaskManager.cpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/gcTaskManager.cpp index b0bcd89afcf..a35c0913138 100644 --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/gcTaskManager.cpp +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/gcTaskManager.cpp @@ -400,7 +400,8 @@ void GCTaskManager::initialize() { assert(workers() != 0, "no workers"); _monitor = new Monitor(Mutex::barrier, // rank "GCTaskManager monitor", // name - Mutex::_allow_vm_block_flag); // allow_vm_block + Mutex::_allow_vm_block_flag, // allow_vm_block + Monitor::_safepoint_check_never); // The queue for the GCTaskManager must be a CHeapObj. GCTaskQueue* unsynchronized_queue = GCTaskQueue::create_on_c_heap(); _queue = SynchronizedGCTaskQueue::create(unsynchronized_queue, lock()); @@ -1125,7 +1126,8 @@ Monitor* MonitorSupply::reserve() { } else { result = new Monitor(Mutex::barrier, // rank "MonitorSupply monitor", // name - Mutex::_allow_vm_block_flag); // allow_vm_block + Mutex::_allow_vm_block_flag, // allow_vm_block + Monitor::_safepoint_check_never); } guarantee(result != NULL, "shouldn't return NULL"); assert(!result->is_locked(), "shouldn't be locked"); diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp index 09ba270569d..e6411517bbb 100644 --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp @@ -195,7 +195,7 @@ bool PSMarkSweep::invoke_no_policy(bool clear_all_softrefs) { COMPILER2_PRESENT(DerivedPointerTable::clear()); - ref_processor()->enable_discovery(true /*verify_disabled*/, true /*verify_no_refs*/); + ref_processor()->enable_discovery(); ref_processor()->setup_policy(clear_all_softrefs); mark_sweep_phase1(clear_all_softrefs); diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.hpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.hpp index 46073f9e293..7b5678db161 100644 --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.hpp +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.hpp @@ -41,31 +41,24 @@ class PSMarkSweep : public MarkSweep { // Closure accessors static OopClosure* mark_and_push_closure() { return &MarkSweep::mark_and_push_closure; } - static VoidClosure* follow_stack_closure() { return (VoidClosure*)&MarkSweep::follow_stack_closure; } + static VoidClosure* follow_stack_closure() { return &MarkSweep::follow_stack_closure; } static CLDClosure* follow_cld_closure() { return &MarkSweep::follow_cld_closure; } - static OopClosure* adjust_pointer_closure() { return (OopClosure*)&MarkSweep::adjust_pointer_closure; } + static OopClosure* adjust_pointer_closure() { return &MarkSweep::adjust_pointer_closure; } static CLDClosure* adjust_cld_closure() { return &MarkSweep::adjust_cld_closure; } - static BoolObjectClosure* is_alive_closure() { return (BoolObjectClosure*)&MarkSweep::is_alive; } + static BoolObjectClosure* is_alive_closure() { return &MarkSweep::is_alive; } - debug_only(public:) // Used for PSParallelCompact debugging // Mark live objects static void mark_sweep_phase1(bool clear_all_softrefs); // Calculate new addresses static void mark_sweep_phase2(); - debug_only(private:) // End used for PSParallelCompact debugging // Update pointers static void mark_sweep_phase3(); // Move objects to new positions static void mark_sweep_phase4(); - debug_only(public:) // Used for PSParallelCompact debugging // Temporary data structures for traversal and storing/restoring marks static void allocate_stacks(); static void deallocate_stacks(); - static void set_ref_processor(ReferenceProcessor* rp) { // delete this method - _ref_processor = rp; - } - debug_only(private:) // End used for PSParallelCompact debugging // If objects are left in eden after a collection, try to move the boundary // and absorb them into the old gen. Returns true if eden was emptied. diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp index b2ef4a192eb..a546e548370 100644 --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp @@ -2069,7 +2069,7 @@ bool PSParallelCompact::invoke_no_policy(bool maximum_heap_compaction) { COMPILER2_PRESENT(DerivedPointerTable::clear()); - ref_processor()->enable_discovery(true /*verify_disabled*/, true /*verify_no_refs*/); + ref_processor()->enable_discovery(); ref_processor()->setup_policy(maximum_heap_compaction); bool marked_for_unloading = false; diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.hpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.hpp index b4ed0137cb1..4016c5179ce 100644 --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.hpp +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.hpp @@ -147,6 +147,10 @@ class PSPromotionManager VALUE_OBJ_CLASS_SPEC { claimed_stack_depth()->push(p); } + inline void promotion_trace_event(oop new_obj, oop old_obj, size_t obj_size, + uint age, bool tenured, + const PSPromotionLAB* lab); + protected: static OopStarTaskQueueSet* stack_array_depth() { return _stack_array_depth; } public: diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.inline.hpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.inline.hpp index b2de74d4175..a33132009c3 100644 --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.inline.hpp +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.inline.hpp @@ -64,6 +64,33 @@ inline void PSPromotionManager::claim_or_forward_depth(T* p) { claim_or_forward_internal_depth(p); } +inline void PSPromotionManager::promotion_trace_event(oop new_obj, oop old_obj, + size_t obj_size, + uint age, bool tenured, + const PSPromotionLAB* lab) { + // Skip if memory allocation failed + if (new_obj != NULL) { + const ParallelScavengeTracer* gc_tracer = PSScavenge::gc_tracer(); + + if (lab != NULL) { + // Promotion of object through newly allocated PLAB + if (gc_tracer->should_report_promotion_in_new_plab_event()) { + size_t obj_bytes = obj_size * HeapWordSize; + size_t lab_size = lab->capacity(); + gc_tracer->report_promotion_in_new_plab_event(old_obj->klass(), obj_bytes, + age, tenured, lab_size); + } + } else { + // Promotion of object directly to heap + if (gc_tracer->should_report_promotion_outside_plab_event()) { + size_t obj_bytes = obj_size * HeapWordSize; + gc_tracer->report_promotion_outside_plab_event(old_obj->klass(), obj_bytes, + age, tenured); + } + } + } +} + // // This method is pretty bulky. It would be nice to split it up // into smaller submethods, but we need to be careful not to hurt @@ -85,11 +112,11 @@ oop PSPromotionManager::copy_to_survivor_space(oop o) { bool new_obj_is_tenured = false; size_t new_obj_size = o->size(); - if (!promote_immediately) { - // Find the objects age, MT safe. - uint age = (test_mark->has_displaced_mark_helper() /* o->has_displaced_mark() */) ? - test_mark->displaced_mark_helper()->age() : test_mark->age(); + // Find the objects age, MT safe. + uint age = (test_mark->has_displaced_mark_helper() /* o->has_displaced_mark() */) ? + test_mark->displaced_mark_helper()->age() : test_mark->age(); + if (!promote_immediately) { // Try allocating obj in to-space (unless too old) if (age < PSScavenge::tenuring_threshold()) { new_obj = (oop) _young_lab.allocate(new_obj_size); @@ -98,6 +125,7 @@ oop PSPromotionManager::copy_to_survivor_space(oop o) { if (new_obj_size > (YoungPLABSize / 2)) { // Allocate this object directly new_obj = (oop)young_space()->cas_allocate(new_obj_size); + promotion_trace_event(new_obj, o, new_obj_size, age, false, NULL); } else { // Flush and fill _young_lab.flush(); @@ -107,6 +135,7 @@ oop PSPromotionManager::copy_to_survivor_space(oop o) { _young_lab.initialize(MemRegion(lab_base, YoungPLABSize)); // Try the young lab allocation again. new_obj = (oop) _young_lab.allocate(new_obj_size); + promotion_trace_event(new_obj, o, new_obj_size, age, false, &_young_lab); } else { _young_gen_is_full = true; } @@ -132,6 +161,7 @@ oop PSPromotionManager::copy_to_survivor_space(oop o) { if (new_obj_size > (OldPLABSize / 2)) { // Allocate this object directly new_obj = (oop)old_gen()->cas_allocate(new_obj_size); + promotion_trace_event(new_obj, o, new_obj_size, age, true, NULL); } else { // Flush and fill _old_lab.flush(); @@ -148,6 +178,7 @@ oop PSPromotionManager::copy_to_survivor_space(oop o) { _old_lab.initialize(MemRegion(lab_base, OldPLABSize)); // Try the old lab allocation again. new_obj = (oop) _old_lab.allocate(new_obj_size); + promotion_trace_event(new_obj, o, new_obj_size, age, true, &_old_lab); } } } diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp index 83fc63b9aa3..5a2f6e1ddd6 100644 --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp @@ -362,7 +362,7 @@ bool PSScavenge::invoke_no_policy() { COMPILER2_PRESENT(DerivedPointerTable::clear()); - reference_processor()->enable_discovery(true /*verify_disabled*/, true /*verify_no_refs*/); + reference_processor()->enable_discovery(); reference_processor()->setup_policy(false); // We track how much was promoted to the next generation for diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.hpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.hpp index 896b705c204..cf1c21d1e49 100644 --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.hpp +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.hpp @@ -92,6 +92,7 @@ class PSScavenge: AllStatic { // Private accessors static CardTableExtension* const card_table() { assert(_card_table != NULL, "Sanity"); return _card_table; } + static const ParallelScavengeTracer* gc_tracer() { return &_gc_tracer; } public: // Accessors diff --git a/hotspot/src/share/vm/gc_implementation/shared/concurrentGCThread.cpp b/hotspot/src/share/vm/gc_implementation/shared/concurrentGCThread.cpp index 2a27f65c8d1..c90da2b0d39 100644 --- a/hotspot/src/share/vm/gc_implementation/shared/concurrentGCThread.cpp +++ b/hotspot/src/share/vm/gc_implementation/shared/concurrentGCThread.cpp @@ -88,7 +88,8 @@ static void _sltLoop(JavaThread* thread, TRAPS) { SurrogateLockerThread::SurrogateLockerThread() : JavaThread(&_sltLoop), - _monitor(Mutex::nonleaf, "SLTMonitor"), + _monitor(Mutex::nonleaf, "SLTMonitor", false, + Monitor::_safepoint_check_sometimes), _buffer(empty) {} diff --git a/hotspot/src/share/vm/gc_implementation/shared/gcTrace.cpp b/hotspot/src/share/vm/gc_implementation/shared/gcTrace.cpp index dba0c5f709b..79af8d24eb4 100644 --- a/hotspot/src/share/vm/gc_implementation/shared/gcTrace.cpp +++ b/hotspot/src/share/vm/gc_implementation/shared/gcTrace.cpp @@ -172,6 +172,27 @@ void YoungGCTracer::report_tenuring_threshold(const uint tenuring_threshold) { _tenuring_threshold = tenuring_threshold; } +bool YoungGCTracer::should_report_promotion_in_new_plab_event() const { + return should_send_promotion_in_new_plab_event(); +} + +bool YoungGCTracer::should_report_promotion_outside_plab_event() const { + return should_send_promotion_outside_plab_event(); +} + +void YoungGCTracer::report_promotion_in_new_plab_event(Klass* klass, size_t obj_size, + uint age, bool tenured, + size_t plab_size) const { + assert_set_gc_id(); + send_promotion_in_new_plab_event(klass, obj_size, age, tenured, plab_size); +} + +void YoungGCTracer::report_promotion_outside_plab_event(Klass* klass, size_t obj_size, + uint age, bool tenured) const { + assert_set_gc_id(); + send_promotion_outside_plab_event(klass, obj_size, age, tenured); +} + void OldGCTracer::report_gc_end_impl(const Ticks& timestamp, TimePartitions* time_partitions) { assert_set_gc_id(); diff --git a/hotspot/src/share/vm/gc_implementation/shared/gcTrace.hpp b/hotspot/src/share/vm/gc_implementation/shared/gcTrace.hpp index 20342ebc244..9774dcb9537 100644 --- a/hotspot/src/share/vm/gc_implementation/shared/gcTrace.hpp +++ b/hotspot/src/share/vm/gc_implementation/shared/gcTrace.hpp @@ -156,9 +156,38 @@ class YoungGCTracer : public GCTracer { void report_promotion_failed(const PromotionFailedInfo& pf_info); void report_tenuring_threshold(const uint tenuring_threshold); + /* + * Methods for reporting Promotion in new or outside PLAB Events. + * + * The object age is always required as it is not certain that the mark word + * of the oop can be trusted at this stage. + * + * obj_size is the size of the promoted object in bytes. + * + * tenured should be true if the object has been promoted to the old + * space during this GC, if the object is copied to survivor space + * from young space or survivor space (aging) tenured should be false. + * + * plab_size is the size of the newly allocated PLAB in bytes. + */ + bool should_report_promotion_in_new_plab_event() const; + bool should_report_promotion_outside_plab_event() const; + void report_promotion_in_new_plab_event(Klass* klass, size_t obj_size, + uint age, bool tenured, + size_t plab_size) const; + void report_promotion_outside_plab_event(Klass* klass, size_t obj_size, + uint age, bool tenured) const; + private: void send_young_gc_event() const; void send_promotion_failed_event(const PromotionFailedInfo& pf_info) const; + bool should_send_promotion_in_new_plab_event() const; + bool should_send_promotion_outside_plab_event() const; + void send_promotion_in_new_plab_event(Klass* klass, size_t obj_size, + uint age, bool tenured, + size_t plab_size) const; + void send_promotion_outside_plab_event(Klass* klass, size_t obj_size, + uint age, bool tenured) const; }; class OldGCTracer : public GCTracer { diff --git a/hotspot/src/share/vm/gc_implementation/shared/gcTraceSend.cpp b/hotspot/src/share/vm/gc_implementation/shared/gcTraceSend.cpp index 97055694fae..326625bf1a8 100644 --- a/hotspot/src/share/vm/gc_implementation/shared/gcTraceSend.cpp +++ b/hotspot/src/share/vm/gc_implementation/shared/gcTraceSend.cpp @@ -111,6 +111,44 @@ void YoungGCTracer::send_young_gc_event() const { } } +bool YoungGCTracer::should_send_promotion_in_new_plab_event() const { + return EventPromoteObjectInNewPLAB::is_enabled(); +} + +bool YoungGCTracer::should_send_promotion_outside_plab_event() const { + return EventPromoteObjectOutsidePLAB::is_enabled(); +} + +void YoungGCTracer::send_promotion_in_new_plab_event(Klass* klass, size_t obj_size, + uint age, bool tenured, + size_t plab_size) const { + + EventPromoteObjectInNewPLAB event; + if (event.should_commit()) { + event.set_gcId(_shared_gc_info.gc_id().id()); + event.set_class(klass); + event.set_objectSize(obj_size); + event.set_tenured(tenured); + event.set_tenuringAge(age); + event.set_plabSize(plab_size); + event.commit(); + } +} + +void YoungGCTracer::send_promotion_outside_plab_event(Klass* klass, size_t obj_size, + uint age, bool tenured) const { + + EventPromoteObjectOutsidePLAB event; + if (event.should_commit()) { + event.set_gcId(_shared_gc_info.gc_id().id()); + event.set_class(klass); + event.set_objectSize(obj_size); + event.set_tenured(tenured); + event.set_tenuringAge(age); + event.commit(); + } +} + void OldGCTracer::send_old_gc_event() const { EventGCOldGarbageCollection e(UNTIMED); if (e.should_commit()) { diff --git a/hotspot/src/share/vm/gc_implementation/shared/mutableSpace.cpp b/hotspot/src/share/vm/gc_implementation/shared/mutableSpace.cpp index f5661fbb412..a87a2494a0b 100644 --- a/hotspot/src/share/vm/gc_implementation/shared/mutableSpace.cpp +++ b/hotspot/src/share/vm/gc_implementation/shared/mutableSpace.cpp @@ -63,9 +63,7 @@ void MutableSpace::numa_setup_pages(MemRegion mr, bool clear_space) { } void MutableSpace::pretouch_pages(MemRegion mr) { - for (volatile char *p = (char*)mr.start(); p < (char*)mr.end(); p += os::vm_page_size()) { - char t = *p; *p = t; - } + os::pretouch_memory((char*)mr.start(), (char*)mr.end()); } void MutableSpace::initialize(MemRegion mr, diff --git a/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp b/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp index 53be23d848b..18488331b39 100644 --- a/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp +++ b/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp @@ -385,6 +385,22 @@ IRT_ENTRY(address, InterpreterRuntime::exception_handler_for_exception(JavaThrea int handler_bci; int current_bci = bci(thread); + if (thread->frames_to_pop_failed_realloc() > 0) { + // Allocation of scalar replaced object used in this frame + // failed. Unconditionally pop the frame. + thread->dec_frames_to_pop_failed_realloc(); + thread->set_vm_result(h_exception()); + // If the method is synchronized we already unlocked the monitor + // during deoptimization so the interpreter needs to skip it when + // the frame is popped. + thread->set_do_not_unlock_if_synchronized(true); +#ifdef CC_INTERP + return (address) -1; +#else + return Interpreter::remove_activation_entry(); +#endif + } + // Need to do this check first since when _do_not_unlock_if_synchronized // is set, we don't want to trigger any classloading which may make calls // into java, or surprisingly find a matching exception handler for bci 0 diff --git a/hotspot/src/share/vm/memory/cardGeneration.cpp b/hotspot/src/share/vm/memory/cardGeneration.cpp new file mode 100644 index 00000000000..21e8d9e51a7 --- /dev/null +++ b/hotspot/src/share/vm/memory/cardGeneration.cpp @@ -0,0 +1,360 @@ +/* + * 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. + * + */ + +#include "precompiled.hpp" + +#include "memory/blockOffsetTable.inline.hpp" +#include "memory/cardGeneration.inline.hpp" +#include "memory/gcLocker.hpp" +#include "memory/generationSpec.hpp" +#include "memory/genOopClosures.inline.hpp" +#include "memory/genRemSet.hpp" +#include "memory/iterator.hpp" +#include "memory/memRegion.hpp" +#include "memory/space.inline.hpp" +#include "runtime/java.hpp" + +CardGeneration::CardGeneration(ReservedSpace rs, size_t initial_byte_size, + int level, + GenRemSet* remset) : + Generation(rs, initial_byte_size, level), _rs(remset), + _shrink_factor(0), _min_heap_delta_bytes(), _capacity_at_prologue(), + _used_at_prologue() +{ + HeapWord* start = (HeapWord*)rs.base(); + size_t reserved_byte_size = rs.size(); + assert((uintptr_t(start) & 3) == 0, "bad alignment"); + assert((reserved_byte_size & 3) == 0, "bad alignment"); + MemRegion reserved_mr(start, heap_word_size(reserved_byte_size)); + _bts = new BlockOffsetSharedArray(reserved_mr, + heap_word_size(initial_byte_size)); + MemRegion committed_mr(start, heap_word_size(initial_byte_size)); + _rs->resize_covered_region(committed_mr); + if (_bts == NULL) { + vm_exit_during_initialization("Could not allocate a BlockOffsetArray"); + } + + // Verify that the start and end of this generation is the start of a card. + // If this wasn't true, a single card could span more than on generation, + // which would cause problems when we commit/uncommit memory, and when we + // clear and dirty cards. + guarantee(_rs->is_aligned(reserved_mr.start()), "generation must be card aligned"); + if (reserved_mr.end() != Universe::heap()->reserved_region().end()) { + // Don't check at the very end of the heap as we'll assert that we're probing off + // the end if we try. + guarantee(_rs->is_aligned(reserved_mr.end()), "generation must be card aligned"); + } + _min_heap_delta_bytes = MinHeapDeltaBytes; + _capacity_at_prologue = initial_byte_size; + _used_at_prologue = 0; +} + +bool CardGeneration::grow_by(size_t bytes) { + assert_correct_size_change_locking(); + bool result = _virtual_space.expand_by(bytes); + if (result) { + size_t new_word_size = + heap_word_size(_virtual_space.committed_size()); + MemRegion mr(space()->bottom(), new_word_size); + // Expand card table + Universe::heap()->barrier_set()->resize_covered_region(mr); + // Expand shared block offset array + _bts->resize(new_word_size); + + // Fix for bug #4668531 + if (ZapUnusedHeapArea) { + MemRegion mangle_region(space()->end(), + (HeapWord*)_virtual_space.high()); + SpaceMangler::mangle_region(mangle_region); + } + + // Expand space -- also expands space's BOT + // (which uses (part of) shared array above) + space()->set_end((HeapWord*)_virtual_space.high()); + + // update the space and generation capacity counters + update_counters(); + + if (Verbose && PrintGC) { + size_t new_mem_size = _virtual_space.committed_size(); + size_t old_mem_size = new_mem_size - bytes; + gclog_or_tty->print_cr("Expanding %s from " SIZE_FORMAT "K by " + SIZE_FORMAT "K to " SIZE_FORMAT "K", + name(), old_mem_size/K, bytes/K, new_mem_size/K); + } + } + return result; +} + +bool CardGeneration::expand(size_t bytes, size_t expand_bytes) { + assert_locked_or_safepoint(Heap_lock); + if (bytes == 0) { + return true; // That's what grow_by(0) would return + } + size_t aligned_bytes = ReservedSpace::page_align_size_up(bytes); + if (aligned_bytes == 0){ + // The alignment caused the number of bytes to wrap. An expand_by(0) will + // return true with the implication that an expansion was done when it + // was not. A call to expand implies a best effort to expand by "bytes" + // but not a guarantee. Align down to give a best effort. This is likely + // the most that the generation can expand since it has some capacity to + // start with. + aligned_bytes = ReservedSpace::page_align_size_down(bytes); + } + size_t aligned_expand_bytes = ReservedSpace::page_align_size_up(expand_bytes); + bool success = false; + if (aligned_expand_bytes > aligned_bytes) { + success = grow_by(aligned_expand_bytes); + } + if (!success) { + success = grow_by(aligned_bytes); + } + if (!success) { + success = grow_to_reserved(); + } + if (PrintGC && Verbose) { + if (success && GC_locker::is_active_and_needs_gc()) { + gclog_or_tty->print_cr("Garbage collection disabled, expanded heap instead"); + } + } + + return success; +} + +bool CardGeneration::grow_to_reserved() { + assert_correct_size_change_locking(); + bool success = true; + const size_t remaining_bytes = _virtual_space.uncommitted_size(); + if (remaining_bytes > 0) { + success = grow_by(remaining_bytes); + DEBUG_ONLY(if (!success) warning("grow to reserved failed");) + } + return success; +} + +void CardGeneration::shrink(size_t bytes) { + assert_correct_size_change_locking(); + + size_t size = ReservedSpace::page_align_size_down(bytes); + if (size == 0) { + return; + } + + // Shrink committed space + _virtual_space.shrink_by(size); + // Shrink space; this also shrinks the space's BOT + space()->set_end((HeapWord*) _virtual_space.high()); + size_t new_word_size = heap_word_size(space()->capacity()); + // Shrink the shared block offset array + _bts->resize(new_word_size); + MemRegion mr(space()->bottom(), new_word_size); + // Shrink the card table + Universe::heap()->barrier_set()->resize_covered_region(mr); + + if (Verbose && PrintGC) { + size_t new_mem_size = _virtual_space.committed_size(); + size_t old_mem_size = new_mem_size + size; + gclog_or_tty->print_cr("Shrinking %s from " SIZE_FORMAT "K to " SIZE_FORMAT "K", + name(), old_mem_size/K, new_mem_size/K); + } +} + +// No young generation references, clear this generation's cards. +void CardGeneration::clear_remembered_set() { + _rs->clear(reserved()); +} + +// Objects in this generation may have moved, invalidate this +// generation's cards. +void CardGeneration::invalidate_remembered_set() { + _rs->invalidate(used_region()); +} + +void CardGeneration::compute_new_size() { + assert(_shrink_factor <= 100, "invalid shrink factor"); + size_t current_shrink_factor = _shrink_factor; + _shrink_factor = 0; + + // We don't have floating point command-line arguments + // Note: argument processing ensures that MinHeapFreeRatio < 100. + const double minimum_free_percentage = MinHeapFreeRatio / 100.0; + const double maximum_used_percentage = 1.0 - minimum_free_percentage; + + // Compute some numbers about the state of the heap. + const size_t used_after_gc = used(); + const size_t capacity_after_gc = capacity(); + + const double min_tmp = used_after_gc / maximum_used_percentage; + size_t minimum_desired_capacity = (size_t)MIN2(min_tmp, double(max_uintx)); + // Don't shrink less than the initial generation size + minimum_desired_capacity = MAX2(minimum_desired_capacity, + spec()->init_size()); + assert(used_after_gc <= minimum_desired_capacity, "sanity check"); + + if (PrintGC && Verbose) { + const size_t free_after_gc = free(); + const double free_percentage = ((double)free_after_gc) / capacity_after_gc; + gclog_or_tty->print_cr("TenuredGeneration::compute_new_size: "); + gclog_or_tty->print_cr(" " + " minimum_free_percentage: %6.2f" + " maximum_used_percentage: %6.2f", + minimum_free_percentage, + maximum_used_percentage); + gclog_or_tty->print_cr(" " + " free_after_gc : %6.1fK" + " used_after_gc : %6.1fK" + " capacity_after_gc : %6.1fK", + free_after_gc / (double) K, + used_after_gc / (double) K, + capacity_after_gc / (double) K); + gclog_or_tty->print_cr(" " + " free_percentage: %6.2f", + free_percentage); + } + + if (capacity_after_gc < minimum_desired_capacity) { + // If we have less free space than we want then expand + size_t expand_bytes = minimum_desired_capacity - capacity_after_gc; + // Don't expand unless it's significant + if (expand_bytes >= _min_heap_delta_bytes) { + expand(expand_bytes, 0); // safe if expansion fails + } + if (PrintGC && Verbose) { + gclog_or_tty->print_cr(" expanding:" + " minimum_desired_capacity: %6.1fK" + " expand_bytes: %6.1fK" + " _min_heap_delta_bytes: %6.1fK", + minimum_desired_capacity / (double) K, + expand_bytes / (double) K, + _min_heap_delta_bytes / (double) K); + } + return; + } + + // No expansion, now see if we want to shrink + size_t shrink_bytes = 0; + // We would never want to shrink more than this + size_t max_shrink_bytes = capacity_after_gc - minimum_desired_capacity; + + if (MaxHeapFreeRatio < 100) { + const double maximum_free_percentage = MaxHeapFreeRatio / 100.0; + const double minimum_used_percentage = 1.0 - maximum_free_percentage; + const double max_tmp = used_after_gc / minimum_used_percentage; + size_t maximum_desired_capacity = (size_t)MIN2(max_tmp, double(max_uintx)); + maximum_desired_capacity = MAX2(maximum_desired_capacity, + spec()->init_size()); + if (PrintGC && Verbose) { + gclog_or_tty->print_cr(" " + " maximum_free_percentage: %6.2f" + " minimum_used_percentage: %6.2f", + maximum_free_percentage, + minimum_used_percentage); + gclog_or_tty->print_cr(" " + " _capacity_at_prologue: %6.1fK" + " minimum_desired_capacity: %6.1fK" + " maximum_desired_capacity: %6.1fK", + _capacity_at_prologue / (double) K, + minimum_desired_capacity / (double) K, + maximum_desired_capacity / (double) K); + } + assert(minimum_desired_capacity <= maximum_desired_capacity, + "sanity check"); + + if (capacity_after_gc > maximum_desired_capacity) { + // Capacity too large, compute shrinking size + shrink_bytes = capacity_after_gc - maximum_desired_capacity; + // We don't want shrink all the way back to initSize if people call + // System.gc(), because some programs do that between "phases" and then + // we'd just have to grow the heap up again for the next phase. So we + // damp the shrinking: 0% on the first call, 10% on the second call, 40% + // on the third call, and 100% by the fourth call. But if we recompute + // size without shrinking, it goes back to 0%. + shrink_bytes = shrink_bytes / 100 * current_shrink_factor; + assert(shrink_bytes <= max_shrink_bytes, "invalid shrink size"); + if (current_shrink_factor == 0) { + _shrink_factor = 10; + } else { + _shrink_factor = MIN2(current_shrink_factor * 4, (size_t) 100); + } + if (PrintGC && Verbose) { + gclog_or_tty->print_cr(" " + " shrinking:" + " initSize: %.1fK" + " maximum_desired_capacity: %.1fK", + spec()->init_size() / (double) K, + maximum_desired_capacity / (double) K); + gclog_or_tty->print_cr(" " + " shrink_bytes: %.1fK" + " current_shrink_factor: " SIZE_FORMAT + " new shrink factor: " SIZE_FORMAT + " _min_heap_delta_bytes: %.1fK", + shrink_bytes / (double) K, + current_shrink_factor, + _shrink_factor, + _min_heap_delta_bytes / (double) K); + } + } + } + + if (capacity_after_gc > _capacity_at_prologue) { + // We might have expanded for promotions, in which case we might want to + // take back that expansion if there's room after GC. That keeps us from + // stretching the heap with promotions when there's plenty of room. + size_t expansion_for_promotion = capacity_after_gc - _capacity_at_prologue; + expansion_for_promotion = MIN2(expansion_for_promotion, max_shrink_bytes); + // We have two shrinking computations, take the largest + shrink_bytes = MAX2(shrink_bytes, expansion_for_promotion); + assert(shrink_bytes <= max_shrink_bytes, "invalid shrink size"); + if (PrintGC && Verbose) { + gclog_or_tty->print_cr(" " + " aggressive shrinking:" + " _capacity_at_prologue: %.1fK" + " capacity_after_gc: %.1fK" + " expansion_for_promotion: %.1fK" + " shrink_bytes: %.1fK", + capacity_after_gc / (double) K, + _capacity_at_prologue / (double) K, + expansion_for_promotion / (double) K, + shrink_bytes / (double) K); + } + } + // Don't shrink unless it's significant + if (shrink_bytes >= _min_heap_delta_bytes) { + shrink(shrink_bytes); + } +} + +// Currently nothing to do. +void CardGeneration::prepare_for_verify() {} + +void CardGeneration::space_iterate(SpaceClosure* blk, + bool usedOnly) { + blk->do_space(space()); +} + +void CardGeneration::younger_refs_iterate(OopsInGenClosure* blk) { + blk->set_generation(this); + younger_refs_in_space_iterate(space(), blk); + blk->reset_generation(); +} diff --git a/hotspot/src/share/vm/memory/cardGeneration.hpp b/hotspot/src/share/vm/memory/cardGeneration.hpp new file mode 100644 index 00000000000..24d0fa0f2c2 --- /dev/null +++ b/hotspot/src/share/vm/memory/cardGeneration.hpp @@ -0,0 +1,99 @@ +/* + * 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. + * + */ + +#ifndef SHARE_VM_MEMORY_CARDGENERATION_HPP +#define SHARE_VM_MEMORY_CARDGENERATION_HPP + +// Class CardGeneration is a generation that is covered by a card table, +// and uses a card-size block-offset array to implement block_start. + +#include "memory/generation.hpp" + +class BlockOffsetSharedArray; +class CompactibleSpace; + +class CardGeneration: public Generation { + friend class VMStructs; + protected: + // This is shared with other generations. + GenRemSet* _rs; + // This is local to this generation. + BlockOffsetSharedArray* _bts; + + // Current shrinking effect: this damps shrinking when the heap gets empty. + size_t _shrink_factor; + + size_t _min_heap_delta_bytes; // Minimum amount to expand. + + // Some statistics from before gc started. + // These are gathered in the gc_prologue (and should_collect) + // to control growing/shrinking policy in spite of promotions. + size_t _capacity_at_prologue; + size_t _used_at_prologue; + + CardGeneration(ReservedSpace rs, size_t initial_byte_size, int level, + GenRemSet* remset); + + virtual void assert_correct_size_change_locking() = 0; + + virtual CompactibleSpace* space() const = 0; + + public: + + // Attempt to expand the generation by "bytes". Expand by at a + // minimum "expand_bytes". Return true if some amount (not + // necessarily the full "bytes") was done. + virtual bool expand(size_t bytes, size_t expand_bytes); + + // Shrink generation with specified size + virtual void shrink(size_t bytes); + + virtual void compute_new_size(); + + virtual void clear_remembered_set(); + + virtual void invalidate_remembered_set(); + + virtual void prepare_for_verify(); + + // Grow generation with specified size (returns false if unable to grow) + bool grow_by(size_t bytes); + // Grow generation to reserved size. + bool grow_to_reserved(); + + size_t capacity() const; + size_t used() const; + size_t free() const; + MemRegion used_region() const; + + void space_iterate(SpaceClosure* blk, bool usedOnly = false); + + void younger_refs_iterate(OopsInGenClosure* blk); + + bool is_in(const void* p) const; + + CompactibleSpace* first_compaction_space() const; +}; + +#endif // SHARE_VM_MEMORY_CARDGENERATION_HPP diff --git a/hotspot/src/share/vm/memory/cardGeneration.inline.hpp b/hotspot/src/share/vm/memory/cardGeneration.inline.hpp new file mode 100644 index 00000000000..fb49d0d0718 --- /dev/null +++ b/hotspot/src/share/vm/memory/cardGeneration.inline.hpp @@ -0,0 +1,55 @@ +/* + * 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. + * + */ + +#ifndef SHARE_VM_MEMORY_CARDGENERATION_INLINE_HPP +#define SHARE_VM_MEMORY_CARDGENERATION_INLINE_HPP + +#include "memory/cardGeneration.hpp" +#include "memory/space.hpp" + +inline size_t CardGeneration::capacity() const { + return space()->capacity(); +} + +inline size_t CardGeneration::used() const { + return space()->used(); +} + +inline size_t CardGeneration::free() const { + return space()->free(); +} + +inline MemRegion CardGeneration::used_region() const { + return space()->used_region(); +} + +inline bool CardGeneration::is_in(const void* p) const { + return space()->is_in(p); +} + +inline CompactibleSpace* CardGeneration::first_compaction_space() const { + return space(); +} + +#endif // SHARE_VM_MEMORY_CARDGENERATION_INLINE_HPP diff --git a/hotspot/src/share/vm/memory/cardTableModRefBS.cpp b/hotspot/src/share/vm/memory/cardTableModRefBS.cpp index d9460308ac7..d3586332b2f 100644 --- a/hotspot/src/share/vm/memory/cardTableModRefBS.cpp +++ b/hotspot/src/share/vm/memory/cardTableModRefBS.cpp @@ -275,29 +275,26 @@ void CardTableModRefBS::resize_covered_region(MemRegion new_region) { // the new_end_aligned does not intrude onto the committed // space of another region. int ri = 0; - for (ri = 0; ri < _cur_covered_regions; ri++) { - if (ri != ind) { - if (_committed[ri].contains(new_end_aligned)) { - // The prior check included in the assert - // (new_end_aligned >= _committed[ri].start()) - // is redundant with the "contains" test. - // Any region containing the new end - // should start at or beyond the region found (ind) - // for the new end (committed regions are not expected to - // be proper subsets of other committed regions). - assert(_committed[ri].start() >= _committed[ind].start(), - "New end of committed region is inconsistent"); - new_end_aligned = _committed[ri].start(); - // new_end_aligned can be equal to the start of its - // committed region (i.e., of "ind") if a second - // region following "ind" also start at the same location - // as "ind". - assert(new_end_aligned >= _committed[ind].start(), - "New end of committed region is before start"); - debug_only(collided = true;) - // Should only collide with 1 region - break; - } + for (ri = ind + 1; ri < _cur_covered_regions; ri++) { + if (new_end_aligned > _committed[ri].start()) { + assert(new_end_aligned <= _committed[ri].end(), + "An earlier committed region can't cover a later committed region"); + // Any region containing the new end + // should start at or beyond the region found (ind) + // for the new end (committed regions are not expected to + // be proper subsets of other committed regions). + assert(_committed[ri].start() >= _committed[ind].start(), + "New end of committed region is inconsistent"); + new_end_aligned = _committed[ri].start(); + // new_end_aligned can be equal to the start of its + // committed region (i.e., of "ind") if a second + // region following "ind" also start at the same location + // as "ind". + assert(new_end_aligned >= _committed[ind].start(), + "New end of committed region is before start"); + debug_only(collided = true;) + // Should only collide with 1 region + break; } } #ifdef ASSERT diff --git a/hotspot/src/share/vm/memory/cardTableRS.cpp b/hotspot/src/share/vm/memory/cardTableRS.cpp index 016fcc920ef..45e20deec48 100644 --- a/hotspot/src/share/vm/memory/cardTableRS.cpp +++ b/hotspot/src/share/vm/memory/cardTableRS.cpp @@ -33,24 +33,13 @@ #include "runtime/java.hpp" #include "runtime/os.hpp" #include "utilities/macros.hpp" -#if INCLUDE_ALL_GCS -#include "gc_implementation/g1/concurrentMark.hpp" -#include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp" -#endif // INCLUDE_ALL_GCS CardTableRS::CardTableRS(MemRegion whole_heap) : GenRemSet(), _cur_youngergen_card_val(youngergenP1_card) { -#if INCLUDE_ALL_GCS - if (UseG1GC) { - _ct_bs = new G1SATBCardTableLoggingModRefBS(whole_heap); - } else { - _ct_bs = new CardTableModRefBSForCTRS(whole_heap); - } -#else + guarantee(Universe::heap()->kind() == CollectedHeap::GenCollectedHeap, "sanity"); _ct_bs = new CardTableModRefBSForCTRS(whole_heap); -#endif _ct_bs->initialize(); set_bs(_ct_bs); _last_cur_val_in_gen = NEW_C_HEAP_ARRAY3(jbyte, GenCollectedHeap::max_gens + 1, diff --git a/hotspot/src/share/vm/memory/filemap.cpp b/hotspot/src/share/vm/memory/filemap.cpp index c9c3e6233d6..cbe369f327e 100644 --- a/hotspot/src/share/vm/memory/filemap.cpp +++ b/hotspot/src/share/vm/memory/filemap.cpp @@ -98,11 +98,11 @@ void FileMapInfo::fail_continue(const char *msg, ...) { tty->print_cr("UseSharedSpaces: %s", msg); } } + UseSharedSpaces = false; + assert(current_info() != NULL, "singleton must be registered"); + current_info()->close(); } va_end(ap); - UseSharedSpaces = false; - assert(current_info() != NULL, "singleton must be registered"); - current_info()->close(); } // Fill in the fileMapInfo structure with data about this VM instance. diff --git a/hotspot/src/share/vm/memory/genCollectedHeap.cpp b/hotspot/src/share/vm/memory/genCollectedHeap.cpp index 4677975dd5b..392f896de1f 100644 --- a/hotspot/src/share/vm/memory/genCollectedHeap.cpp +++ b/hotspot/src/share/vm/memory/genCollectedHeap.cpp @@ -70,6 +70,7 @@ enum GCH_strong_roots_tasks { GenCollectedHeap::GenCollectedHeap(GenCollectorPolicy *policy) : SharedHeap(policy), + _rem_set(NULL), _gen_policy(policy), _gen_process_roots_tasks(new SubTasksDone(GCH_PS_NumElements)), _full_collections_completed(0) @@ -465,7 +466,7 @@ void GenCollectedHeap::do_collection(bool full, // atomic wrt other collectors in this configuration, we // are guaranteed to have empty discovered ref lists. if (rp->discovery_is_atomic()) { - rp->enable_discovery(true /*verify_disabled*/, true /*verify_no_refs*/); + rp->enable_discovery(); rp->setup_policy(do_clear_all_soft_refs); } else { // collect() below will enable discovery as appropriate diff --git a/hotspot/src/share/vm/memory/genCollectedHeap.hpp b/hotspot/src/share/vm/memory/genCollectedHeap.hpp index db4133560fc..dc132f67f1a 100644 --- a/hotspot/src/share/vm/memory/genCollectedHeap.hpp +++ b/hotspot/src/share/vm/memory/genCollectedHeap.hpp @@ -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 @@ -66,6 +66,9 @@ public: Generation* _gens[max_gens]; GenerationSpec** _gen_specs; + // The singleton Gen Remembered Set. + GenRemSet* _rem_set; + // The generational collector policy. GenCollectorPolicy* _gen_policy; @@ -383,6 +386,10 @@ public: return _n_gens; } + // This function returns the "GenRemSet" object that allows us to scan + // generations in a fully generational heap. + GenRemSet* rem_set() { return _rem_set; } + // Convenience function to be used in situations where the heap type can be // asserted to be this type. static GenCollectedHeap* heap(); diff --git a/hotspot/src/share/vm/memory/genOopClosures.inline.hpp b/hotspot/src/share/vm/memory/genOopClosures.inline.hpp index 30c77dba0ea..3b2b83dfa0c 100644 --- a/hotspot/src/share/vm/memory/genOopClosures.inline.hpp +++ b/hotspot/src/share/vm/memory/genOopClosures.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 @@ -44,7 +44,7 @@ inline void OopsInGenClosure::set_generation(Generation* gen) { _gen_boundary = _gen->reserved().start(); // Barrier set for the heap, must be set after heap is initialized if (_rs == NULL) { - GenRemSet* rs = SharedHeap::heap()->rem_set(); + GenRemSet* rs = GenCollectedHeap::heap()->rem_set(); _rs = (CardTableRS*)rs; } } diff --git a/hotspot/src/share/vm/memory/generation.cpp b/hotspot/src/share/vm/memory/generation.cpp index 87880cf0e31..f1b7620bed5 100644 --- a/hotspot/src/share/vm/memory/generation.cpp +++ b/hotspot/src/share/vm/memory/generation.cpp @@ -297,7 +297,7 @@ void Generation::oop_iterate(ExtendedOopClosure* cl) { void Generation::younger_refs_in_space_iterate(Space* sp, OopsInGenClosure* cl) { - GenRemSet* rs = SharedHeap::heap()->rem_set(); + GenRemSet* rs = GenCollectedHeap::heap()->rem_set(); rs->younger_refs_in_space_iterate(sp, cl); } @@ -361,244 +361,3 @@ void Generation::compact() { sp = sp->next_compaction_space(); } } - -CardGeneration::CardGeneration(ReservedSpace rs, size_t initial_byte_size, - int level, - GenRemSet* remset) : - Generation(rs, initial_byte_size, level), _rs(remset), - _shrink_factor(0), _min_heap_delta_bytes(), _capacity_at_prologue(), - _used_at_prologue() -{ - HeapWord* start = (HeapWord*)rs.base(); - size_t reserved_byte_size = rs.size(); - assert((uintptr_t(start) & 3) == 0, "bad alignment"); - assert((reserved_byte_size & 3) == 0, "bad alignment"); - MemRegion reserved_mr(start, heap_word_size(reserved_byte_size)); - _bts = new BlockOffsetSharedArray(reserved_mr, - heap_word_size(initial_byte_size)); - MemRegion committed_mr(start, heap_word_size(initial_byte_size)); - _rs->resize_covered_region(committed_mr); - if (_bts == NULL) - vm_exit_during_initialization("Could not allocate a BlockOffsetArray"); - - // Verify that the start and end of this generation is the start of a card. - // If this wasn't true, a single card could span more than on generation, - // which would cause problems when we commit/uncommit memory, and when we - // clear and dirty cards. - guarantee(_rs->is_aligned(reserved_mr.start()), "generation must be card aligned"); - if (reserved_mr.end() != Universe::heap()->reserved_region().end()) { - // Don't check at the very end of the heap as we'll assert that we're probing off - // the end if we try. - guarantee(_rs->is_aligned(reserved_mr.end()), "generation must be card aligned"); - } - _min_heap_delta_bytes = MinHeapDeltaBytes; - _capacity_at_prologue = initial_byte_size; - _used_at_prologue = 0; -} - -bool CardGeneration::expand(size_t bytes, size_t expand_bytes) { - assert_locked_or_safepoint(Heap_lock); - if (bytes == 0) { - return true; // That's what grow_by(0) would return - } - size_t aligned_bytes = ReservedSpace::page_align_size_up(bytes); - if (aligned_bytes == 0){ - // The alignment caused the number of bytes to wrap. An expand_by(0) will - // return true with the implication that an expansion was done when it - // was not. A call to expand implies a best effort to expand by "bytes" - // but not a guarantee. Align down to give a best effort. This is likely - // the most that the generation can expand since it has some capacity to - // start with. - aligned_bytes = ReservedSpace::page_align_size_down(bytes); - } - size_t aligned_expand_bytes = ReservedSpace::page_align_size_up(expand_bytes); - bool success = false; - if (aligned_expand_bytes > aligned_bytes) { - success = grow_by(aligned_expand_bytes); - } - if (!success) { - success = grow_by(aligned_bytes); - } - if (!success) { - success = grow_to_reserved(); - } - if (PrintGC && Verbose) { - if (success && GC_locker::is_active_and_needs_gc()) { - gclog_or_tty->print_cr("Garbage collection disabled, expanded heap instead"); - } - } - - return success; -} - - -// No young generation references, clear this generation's cards. -void CardGeneration::clear_remembered_set() { - _rs->clear(reserved()); -} - - -// Objects in this generation may have moved, invalidate this -// generation's cards. -void CardGeneration::invalidate_remembered_set() { - _rs->invalidate(used_region()); -} - - -void CardGeneration::compute_new_size() { - assert(_shrink_factor <= 100, "invalid shrink factor"); - size_t current_shrink_factor = _shrink_factor; - _shrink_factor = 0; - - // We don't have floating point command-line arguments - // Note: argument processing ensures that MinHeapFreeRatio < 100. - const double minimum_free_percentage = MinHeapFreeRatio / 100.0; - const double maximum_used_percentage = 1.0 - minimum_free_percentage; - - // Compute some numbers about the state of the heap. - const size_t used_after_gc = used(); - const size_t capacity_after_gc = capacity(); - - const double min_tmp = used_after_gc / maximum_used_percentage; - size_t minimum_desired_capacity = (size_t)MIN2(min_tmp, double(max_uintx)); - // Don't shrink less than the initial generation size - minimum_desired_capacity = MAX2(minimum_desired_capacity, - spec()->init_size()); - assert(used_after_gc <= minimum_desired_capacity, "sanity check"); - - if (PrintGC && Verbose) { - const size_t free_after_gc = free(); - const double free_percentage = ((double)free_after_gc) / capacity_after_gc; - gclog_or_tty->print_cr("TenuredGeneration::compute_new_size: "); - gclog_or_tty->print_cr(" " - " minimum_free_percentage: %6.2f" - " maximum_used_percentage: %6.2f", - minimum_free_percentage, - maximum_used_percentage); - gclog_or_tty->print_cr(" " - " free_after_gc : %6.1fK" - " used_after_gc : %6.1fK" - " capacity_after_gc : %6.1fK", - free_after_gc / (double) K, - used_after_gc / (double) K, - capacity_after_gc / (double) K); - gclog_or_tty->print_cr(" " - " free_percentage: %6.2f", - free_percentage); - } - - if (capacity_after_gc < minimum_desired_capacity) { - // If we have less free space than we want then expand - size_t expand_bytes = minimum_desired_capacity - capacity_after_gc; - // Don't expand unless it's significant - if (expand_bytes >= _min_heap_delta_bytes) { - expand(expand_bytes, 0); // safe if expansion fails - } - if (PrintGC && Verbose) { - gclog_or_tty->print_cr(" expanding:" - " minimum_desired_capacity: %6.1fK" - " expand_bytes: %6.1fK" - " _min_heap_delta_bytes: %6.1fK", - minimum_desired_capacity / (double) K, - expand_bytes / (double) K, - _min_heap_delta_bytes / (double) K); - } - return; - } - - // No expansion, now see if we want to shrink - size_t shrink_bytes = 0; - // We would never want to shrink more than this - size_t max_shrink_bytes = capacity_after_gc - minimum_desired_capacity; - - if (MaxHeapFreeRatio < 100) { - const double maximum_free_percentage = MaxHeapFreeRatio / 100.0; - const double minimum_used_percentage = 1.0 - maximum_free_percentage; - const double max_tmp = used_after_gc / minimum_used_percentage; - size_t maximum_desired_capacity = (size_t)MIN2(max_tmp, double(max_uintx)); - maximum_desired_capacity = MAX2(maximum_desired_capacity, - spec()->init_size()); - if (PrintGC && Verbose) { - gclog_or_tty->print_cr(" " - " maximum_free_percentage: %6.2f" - " minimum_used_percentage: %6.2f", - maximum_free_percentage, - minimum_used_percentage); - gclog_or_tty->print_cr(" " - " _capacity_at_prologue: %6.1fK" - " minimum_desired_capacity: %6.1fK" - " maximum_desired_capacity: %6.1fK", - _capacity_at_prologue / (double) K, - minimum_desired_capacity / (double) K, - maximum_desired_capacity / (double) K); - } - assert(minimum_desired_capacity <= maximum_desired_capacity, - "sanity check"); - - if (capacity_after_gc > maximum_desired_capacity) { - // Capacity too large, compute shrinking size - shrink_bytes = capacity_after_gc - maximum_desired_capacity; - // We don't want shrink all the way back to initSize if people call - // System.gc(), because some programs do that between "phases" and then - // we'd just have to grow the heap up again for the next phase. So we - // damp the shrinking: 0% on the first call, 10% on the second call, 40% - // on the third call, and 100% by the fourth call. But if we recompute - // size without shrinking, it goes back to 0%. - shrink_bytes = shrink_bytes / 100 * current_shrink_factor; - assert(shrink_bytes <= max_shrink_bytes, "invalid shrink size"); - if (current_shrink_factor == 0) { - _shrink_factor = 10; - } else { - _shrink_factor = MIN2(current_shrink_factor * 4, (size_t) 100); - } - if (PrintGC && Verbose) { - gclog_or_tty->print_cr(" " - " shrinking:" - " initSize: %.1fK" - " maximum_desired_capacity: %.1fK", - spec()->init_size() / (double) K, - maximum_desired_capacity / (double) K); - gclog_or_tty->print_cr(" " - " shrink_bytes: %.1fK" - " current_shrink_factor: " SIZE_FORMAT - " new shrink factor: " SIZE_FORMAT - " _min_heap_delta_bytes: %.1fK", - shrink_bytes / (double) K, - current_shrink_factor, - _shrink_factor, - _min_heap_delta_bytes / (double) K); - } - } - } - - if (capacity_after_gc > _capacity_at_prologue) { - // We might have expanded for promotions, in which case we might want to - // take back that expansion if there's room after GC. That keeps us from - // stretching the heap with promotions when there's plenty of room. - size_t expansion_for_promotion = capacity_after_gc - _capacity_at_prologue; - expansion_for_promotion = MIN2(expansion_for_promotion, max_shrink_bytes); - // We have two shrinking computations, take the largest - shrink_bytes = MAX2(shrink_bytes, expansion_for_promotion); - assert(shrink_bytes <= max_shrink_bytes, "invalid shrink size"); - if (PrintGC && Verbose) { - gclog_or_tty->print_cr(" " - " aggressive shrinking:" - " _capacity_at_prologue: %.1fK" - " capacity_after_gc: %.1fK" - " expansion_for_promotion: %.1fK" - " shrink_bytes: %.1fK", - capacity_after_gc / (double) K, - _capacity_at_prologue / (double) K, - expansion_for_promotion / (double) K, - shrink_bytes / (double) K); - } - } - // Don't shrink unless it's significant - if (shrink_bytes >= _min_heap_delta_bytes) { - shrink(shrink_bytes); - } -} - -// Currently nothing to do. -void CardGeneration::prepare_for_verify() {} - diff --git a/hotspot/src/share/vm/memory/generation.hpp b/hotspot/src/share/vm/memory/generation.hpp index e9c352e10b4..058f757de01 100644 --- a/hotspot/src/share/vm/memory/generation.hpp +++ b/hotspot/src/share/vm/memory/generation.hpp @@ -584,57 +584,4 @@ public: virtual CollectorCounters* counters() { return _gc_counters; } }; -// Class CardGeneration is a generation that is covered by a card table, -// and uses a card-size block-offset array to implement block_start. - -// class BlockOffsetArray; -// class BlockOffsetArrayContigSpace; -class BlockOffsetSharedArray; - -class CardGeneration: public Generation { - friend class VMStructs; - protected: - // This is shared with other generations. - GenRemSet* _rs; - // This is local to this generation. - BlockOffsetSharedArray* _bts; - - // current shrinking effect: this damps shrinking when the heap gets empty. - size_t _shrink_factor; - - size_t _min_heap_delta_bytes; // Minimum amount to expand. - - // Some statistics from before gc started. - // These are gathered in the gc_prologue (and should_collect) - // to control growing/shrinking policy in spite of promotions. - size_t _capacity_at_prologue; - size_t _used_at_prologue; - - CardGeneration(ReservedSpace rs, size_t initial_byte_size, int level, - GenRemSet* remset); - - public: - - // Attempt to expand the generation by "bytes". Expand by at a - // minimum "expand_bytes". Return true if some amount (not - // necessarily the full "bytes") was done. - virtual bool expand(size_t bytes, size_t expand_bytes); - - // Shrink generation with specified size (returns false if unable to shrink) - virtual void shrink(size_t bytes) = 0; - - virtual void compute_new_size(); - - virtual void clear_remembered_set(); - - virtual void invalidate_remembered_set(); - - virtual void prepare_for_verify(); - - // Grow generation with specified size (returns false if unable to grow) - virtual bool grow_by(size_t bytes) = 0; - // Grow generation to reserved size. - virtual bool grow_to_reserved() = 0; -}; - #endif // SHARE_VM_MEMORY_GENERATION_HPP diff --git a/hotspot/src/share/vm/memory/metaspace.cpp b/hotspot/src/share/vm/memory/metaspace.cpp index 0b4d69efb83..7448b3e62d7 100644 --- a/hotspot/src/share/vm/memory/metaspace.cpp +++ b/hotspot/src/share/vm/memory/metaspace.cpp @@ -792,7 +792,8 @@ const int SpaceManager::_expand_lock_rank = Monitor::leaf - 1; Mutex* const SpaceManager::_expand_lock = new Mutex(SpaceManager::_expand_lock_rank, SpaceManager::_expand_lock_name, - Mutex::_allow_vm_block_flag); + Mutex::_allow_vm_block_flag, + Monitor::_safepoint_check_never); void VirtualSpaceNode::inc_container_count() { assert_lock_strong(SpaceManager::expand_lock()); @@ -3158,7 +3159,25 @@ void Metaspace::global_initialize() { SharedMiscDataSize = align_size_up(SharedMiscDataSize, max_alignment); SharedMiscCodeSize = align_size_up(SharedMiscCodeSize, max_alignment); - // the min_misc_code_size estimate is based on MetaspaceShared::generate_vtable_methods() + // make sure SharedReadOnlySize and SharedReadWriteSize are not less than + // the minimum values. + if (SharedReadOnlySize < MetaspaceShared::min_ro_size){ + report_out_of_shared_space(SharedReadOnly); + } + + if (SharedReadWriteSize < MetaspaceShared::min_rw_size){ + report_out_of_shared_space(SharedReadWrite); + } + + // the min_misc_data_size and min_misc_code_size estimates are based on + // MetaspaceShared::generate_vtable_methods() + uint min_misc_data_size = align_size_up( + MetaspaceShared::num_virtuals * MetaspaceShared::vtbl_list_size * sizeof(void*), max_alignment); + + if (SharedMiscDataSize < min_misc_data_size) { + report_out_of_shared_space(SharedMiscData); + } + uintx min_misc_code_size = align_size_up( (MetaspaceShared::num_virtuals * MetaspaceShared::vtbl_list_size) * (sizeof(void*) + MetaspaceShared::vtbl_method_size) + MetaspaceShared::vtbl_common_code_size, diff --git a/hotspot/src/share/vm/memory/metaspaceShared.cpp b/hotspot/src/share/vm/memory/metaspaceShared.cpp index b6edbae988a..26729be6efd 100644 --- a/hotspot/src/share/vm/memory/metaspaceShared.cpp +++ b/hotspot/src/share/vm/memory/metaspaceShared.cpp @@ -969,7 +969,7 @@ bool MetaspaceShared::map_shared_spaces(FileMapInfo* mapinfo) { #endif // If -Xshare:on is specified, print out the error message and exit VM, // otherwise, set UseSharedSpaces to false and continue. - if (RequireSharedSpaces) { + if (RequireSharedSpaces || PrintSharedArchiveAndExit) { vm_exit_during_initialization("Unable to use shared archive.", "Failed map_region for using -Xshare:on."); } else { FLAG_SET_DEFAULT(UseSharedSpaces, false); diff --git a/hotspot/src/share/vm/memory/metaspaceShared.hpp b/hotspot/src/share/vm/memory/metaspaceShared.hpp index cb34465ec69..e6e2c9a353e 100644 --- a/hotspot/src/share/vm/memory/metaspaceShared.hpp +++ b/hotspot/src/share/vm/memory/metaspaceShared.hpp @@ -69,6 +69,11 @@ class MetaspaceShared : AllStatic { vtbl_common_code_size = (1*K) // conservative size of the "common_code" for the x64 platform }; + enum { + min_ro_size = NOT_LP64(8*M) LP64_ONLY(9*M), // minimum ro and rw regions sizes based on dumping + min_rw_size = NOT_LP64(7*M) LP64_ONLY(12*M) // of a shared archive using the default classlist + }; + enum { ro = 0, // read-only shared space in the heap rw = 1, // read-write shared space in the heap diff --git a/hotspot/src/share/vm/memory/referenceProcessor.cpp b/hotspot/src/share/vm/memory/referenceProcessor.cpp index 571bc4a7a98..b6edd3a0af2 100644 --- a/hotspot/src/share/vm/memory/referenceProcessor.cpp +++ b/hotspot/src/share/vm/memory/referenceProcessor.cpp @@ -68,10 +68,10 @@ void ReferenceProcessor::init_statics() { _pending_list_uses_discovered_field = JDK_Version::current().pending_list_uses_discovered_field(); } -void ReferenceProcessor::enable_discovery(bool verify_disabled, bool check_no_refs) { +void ReferenceProcessor::enable_discovery(bool check_no_refs) { #ifdef ASSERT // Verify that we're not currently discovering refs - assert(!verify_disabled || !_discovering_refs, "nested call?"); + assert(!_discovering_refs, "nested call?"); if (check_no_refs) { // Verify that the discovered lists are empty @@ -963,52 +963,6 @@ ReferenceProcessor::process_discovered_reflist( return total_list_count; } -void ReferenceProcessor::clean_up_discovered_references() { - // loop over the lists - for (uint i = 0; i < _max_num_q * number_of_subclasses_of_ref(); i++) { - if (TraceReferenceGC && PrintGCDetails && ((i % _max_num_q) == 0)) { - gclog_or_tty->print_cr( - "\nScrubbing %s discovered list of Null referents", - list_name(i)); - } - clean_up_discovered_reflist(_discovered_refs[i]); - } -} - -void ReferenceProcessor::clean_up_discovered_reflist(DiscoveredList& refs_list) { - assert(!discovery_is_atomic(), "Else why call this method?"); - DiscoveredListIterator iter(refs_list, NULL, NULL); - while (iter.has_next()) { - iter.load_ptrs(DEBUG_ONLY(true /* allow_null_referent */)); - oop next = java_lang_ref_Reference::next(iter.obj()); - assert(next->is_oop_or_null(), err_msg("Expected an oop or NULL for next field at " PTR_FORMAT, p2i(next))); - // If referent has been cleared or Reference is not active, - // drop it. - if (iter.referent() == NULL || next != NULL) { - debug_only( - if (PrintGCDetails && TraceReferenceGC) { - gclog_or_tty->print_cr("clean_up_discovered_list: Dropping Reference: " - INTPTR_FORMAT " with next field: " INTPTR_FORMAT - " and referent: " INTPTR_FORMAT, - (void *)iter.obj(), (void *)next, (void *)iter.referent()); - } - ) - // Remove Reference object from list - iter.remove(); - iter.move_to_next(); - } else { - iter.next(); - } - } - NOT_PRODUCT( - if (PrintGCDetails && TraceReferenceGC) { - gclog_or_tty->print( - " Removed %d Refs with NULL referents out of %d discovered Refs", - iter.removed(), iter.processed()); - } - ) -} - inline DiscoveredList* ReferenceProcessor::get_discovered_list(ReferenceType rt) { uint id = 0; // Determine the queue index to use for this object. diff --git a/hotspot/src/share/vm/memory/referenceProcessor.hpp b/hotspot/src/share/vm/memory/referenceProcessor.hpp index d4d2b89866e..3156c00b72f 100644 --- a/hotspot/src/share/vm/memory/referenceProcessor.hpp +++ b/hotspot/src/share/vm/memory/referenceProcessor.hpp @@ -353,19 +353,6 @@ class ReferenceProcessor : public CHeapObj { GCTimer* gc_timer, GCId gc_id); - // Delete entries in the discovered lists that have - // either a null referent or are not active. Such - // Reference objects can result from the clearing - // or enqueueing of Reference objects concurrent - // with their discovery by a (concurrent) collector. - // For a definition of "active" see java.lang.ref.Reference; - // Refs are born active, become inactive when enqueued, - // and never become active again. The state of being - // active is encoded as follows: A Ref is active - // if and only if its "next" field is NULL. - void clean_up_discovered_references(); - void clean_up_discovered_reflist(DiscoveredList& refs_list); - // Returns the name of the discovered reference list // occupying the i / _num_q slot. const char* list_name(uint i); @@ -439,7 +426,7 @@ class ReferenceProcessor : public CHeapObj { void set_span(MemRegion span) { _span = span; } // start and stop weak ref discovery - void enable_discovery(bool verify_disabled, bool check_no_refs); + void enable_discovery(bool check_no_refs = true); void disable_discovery() { _discovering_refs = false; } bool discovery_enabled() { return _discovering_refs; } @@ -517,7 +504,7 @@ class NoRefDiscovery: StackObj { ~NoRefDiscovery() { if (_was_discovering_refs) { - _rp->enable_discovery(true /*verify_disabled*/, false /*check_no_refs*/); + _rp->enable_discovery(false /*check_no_refs*/); } } }; diff --git a/hotspot/src/share/vm/memory/sharedHeap.cpp b/hotspot/src/share/vm/memory/sharedHeap.cpp index 3cf4a316c92..7450cc92879 100644 --- a/hotspot/src/share/vm/memory/sharedHeap.cpp +++ b/hotspot/src/share/vm/memory/sharedHeap.cpp @@ -58,7 +58,6 @@ enum SH_process_roots_tasks { SharedHeap::SharedHeap(CollectorPolicy* policy_) : CollectedHeap(), _collector_policy(policy_), - _rem_set(NULL), _strong_roots_scope(NULL), _strong_roots_parity(0), _process_strong_tasks(new SubTasksDone(SH_PS_NumElements)), @@ -152,7 +151,7 @@ SharedHeap::StrongRootsScope::~StrongRootsScope() { } } -Monitor* SharedHeap::StrongRootsScope::_lock = new Monitor(Mutex::leaf, "StrongRootsScope lock", false); +Monitor* SharedHeap::StrongRootsScope::_lock = new Monitor(Mutex::leaf, "StrongRootsScope lock", false, Monitor::_safepoint_check_never); void SharedHeap::StrongRootsScope::mark_worker_done_with_threads(uint n_workers) { // The Thread work barrier is only needed by G1 Class Unloading. diff --git a/hotspot/src/share/vm/memory/sharedHeap.hpp b/hotspot/src/share/vm/memory/sharedHeap.hpp index c934b6bdf15..91735f1cdaa 100644 --- a/hotspot/src/share/vm/memory/sharedHeap.hpp +++ b/hotspot/src/share/vm/memory/sharedHeap.hpp @@ -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 @@ -114,10 +114,6 @@ protected: // set the static pointer "_sh" to that instance. static SharedHeap* _sh; - // and the Gen Remembered Set, at least one good enough to scan the perm - // gen. - GenRemSet* _rem_set; - // A gc policy, controls global gc resource issues CollectorPolicy *_collector_policy; @@ -152,10 +148,6 @@ public: // Initialization of ("weak") reference processing support virtual void ref_processing_init(); - // This function returns the "GenRemSet" object that allows us to scan - // generations in a fully generational heap. - GenRemSet* rem_set() { return _rem_set; } - // Iteration functions. void oop_iterate(ExtendedOopClosure* cl) = 0; diff --git a/hotspot/src/share/vm/memory/tenuredGeneration.cpp b/hotspot/src/share/vm/memory/tenuredGeneration.cpp index 37cd32c8585..3ad812cb4c2 100644 --- a/hotspot/src/share/vm/memory/tenuredGeneration.cpp +++ b/hotspot/src/share/vm/memory/tenuredGeneration.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 @@ -28,6 +28,7 @@ #include "gc_implementation/shared/parGCAllocBuffer.hpp" #include "memory/allocation.inline.hpp" #include "memory/blockOffsetTable.inline.hpp" +#include "memory/cardGeneration.inline.hpp" #include "memory/generationSpec.hpp" #include "memory/genMarkSweep.hpp" #include "memory/genOopClosures.inline.hpp" @@ -235,34 +236,6 @@ bool TenuredGeneration::expand(size_t bytes, size_t expand_bytes) { return CardGeneration::expand(bytes, expand_bytes); } - -void TenuredGeneration::shrink(size_t bytes) { - assert_locked_or_safepoint(ExpandHeap_lock); - size_t size = ReservedSpace::page_align_size_down(bytes); - if (size > 0) { - shrink_by(size); - } -} - - -size_t TenuredGeneration::capacity() const { - return _the_space->capacity(); -} - - -size_t TenuredGeneration::used() const { - return _the_space->used(); -} - - -size_t TenuredGeneration::free() const { - return _the_space->free(); -} - -MemRegion TenuredGeneration::used_region() const { - return the_space()->used_region(); -} - size_t TenuredGeneration::unsafe_max_alloc_nogc() const { return _the_space->free(); } @@ -271,74 +244,8 @@ size_t TenuredGeneration::contiguous_available() const { return _the_space->free() + _virtual_space.uncommitted_size(); } -bool TenuredGeneration::grow_by(size_t bytes) { +void TenuredGeneration::assert_correct_size_change_locking() { assert_locked_or_safepoint(ExpandHeap_lock); - bool result = _virtual_space.expand_by(bytes); - if (result) { - size_t new_word_size = - heap_word_size(_virtual_space.committed_size()); - MemRegion mr(_the_space->bottom(), new_word_size); - // Expand card table - Universe::heap()->barrier_set()->resize_covered_region(mr); - // Expand shared block offset array - _bts->resize(new_word_size); - - // Fix for bug #4668531 - if (ZapUnusedHeapArea) { - MemRegion mangle_region(_the_space->end(), - (HeapWord*)_virtual_space.high()); - SpaceMangler::mangle_region(mangle_region); - } - - // Expand space -- also expands space's BOT - // (which uses (part of) shared array above) - _the_space->set_end((HeapWord*)_virtual_space.high()); - - // update the space and generation capacity counters - update_counters(); - - if (Verbose && PrintGC) { - size_t new_mem_size = _virtual_space.committed_size(); - size_t old_mem_size = new_mem_size - bytes; - gclog_or_tty->print_cr("Expanding %s from " SIZE_FORMAT "K by " - SIZE_FORMAT "K to " SIZE_FORMAT "K", - name(), old_mem_size/K, bytes/K, new_mem_size/K); - } - } - return result; -} - - -bool TenuredGeneration::grow_to_reserved() { - assert_locked_or_safepoint(ExpandHeap_lock); - bool success = true; - const size_t remaining_bytes = _virtual_space.uncommitted_size(); - if (remaining_bytes > 0) { - success = grow_by(remaining_bytes); - DEBUG_ONLY(if (!success) warning("grow to reserved failed");) - } - return success; -} - -void TenuredGeneration::shrink_by(size_t bytes) { - assert_locked_or_safepoint(ExpandHeap_lock); - // Shrink committed space - _virtual_space.shrink_by(bytes); - // Shrink space; this also shrinks the space's BOT - _the_space->set_end((HeapWord*) _virtual_space.high()); - size_t new_word_size = heap_word_size(_the_space->capacity()); - // Shrink the shared block offset array - _bts->resize(new_word_size); - MemRegion mr(_the_space->bottom(), new_word_size); - // Shrink the card table - Universe::heap()->barrier_set()->resize_covered_region(mr); - - if (Verbose && PrintGC) { - size_t new_mem_size = _virtual_space.committed_size(); - size_t old_mem_size = new_mem_size + bytes; - gclog_or_tty->print_cr("Shrinking %s from " SIZE_FORMAT "K to " SIZE_FORMAT "K", - name(), old_mem_size/K, new_mem_size/K); - } } // Currently nothing to do. @@ -348,27 +255,14 @@ void TenuredGeneration::object_iterate(ObjectClosure* blk) { _the_space->object_iterate(blk); } -void TenuredGeneration::space_iterate(SpaceClosure* blk, - bool usedOnly) { - blk->do_space(_the_space); -} - -void TenuredGeneration::younger_refs_iterate(OopsInGenClosure* blk) { - blk->set_generation(this); - younger_refs_in_space_iterate(_the_space, blk); - blk->reset_generation(); -} - void TenuredGeneration::save_marks() { _the_space->set_saved_mark(); } - void TenuredGeneration::reset_saved_marks() { _the_space->reset_saved_mark(); } - bool TenuredGeneration::no_allocs_since_save_marks() { return _the_space->saved_mark_at_top(); } @@ -387,28 +281,25 @@ ALL_SINCE_SAVE_MARKS_CLOSURES(TenuredGen_SINCE_SAVE_MARKS_ITERATE_DEFN) #undef TenuredGen_SINCE_SAVE_MARKS_ITERATE_DEFN - void TenuredGeneration::gc_epilogue(bool full) { - _last_gc = WaterMark(the_space(), the_space()->top()); - // update the generation and space performance counters update_counters(); if (ZapUnusedHeapArea) { - the_space()->check_mangled_unused_area_complete(); + _the_space->check_mangled_unused_area_complete(); } } void TenuredGeneration::record_spaces_top() { assert(ZapUnusedHeapArea, "Not mangling unused space"); - the_space()->set_top_for_allocations(); + _the_space->set_top_for_allocations(); } void TenuredGeneration::verify() { - the_space()->verify(); + _the_space->verify(); } void TenuredGeneration::print_on(outputStream* st) const { Generation::print_on(st); st->print(" the"); - the_space()->print_on(st); + _the_space->print_on(st); } diff --git a/hotspot/src/share/vm/memory/tenuredGeneration.hpp b/hotspot/src/share/vm/memory/tenuredGeneration.hpp index 0ecd54dd55f..5417e69cb7f 100644 --- a/hotspot/src/share/vm/memory/tenuredGeneration.hpp +++ b/hotspot/src/share/vm/memory/tenuredGeneration.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 @@ -28,7 +28,7 @@ #include "gc_implementation/shared/cSpaceCounters.hpp" #include "gc_implementation/shared/gcStats.hpp" #include "gc_implementation/shared/generationCounters.hpp" -#include "memory/generation.hpp" +#include "memory/cardGeneration.hpp" #include "utilities/macros.hpp" // TenuredGeneration models the heap containing old (promoted/tenured) objects @@ -42,27 +42,18 @@ class TenuredGeneration: public CardGeneration { friend class VM_PopulateDumpSharedSpace; protected: - ContiguousSpace* _the_space; // actual space holding objects - WaterMark _last_gc; // watermark between objects allocated before - // and after last GC. + ContiguousSpace* _the_space; // Actual space holding objects GenerationCounters* _gen_counters; CSpaceCounters* _space_counters; - // Grow generation with specified size (returns false if unable to grow) - virtual bool grow_by(size_t bytes); - // Grow generation to reserved size. - virtual bool grow_to_reserved(); - // Shrink generation with specified size (returns false if unable to shrink) - void shrink_by(size_t bytes); - // Allocation failure virtual bool expand(size_t bytes, size_t expand_bytes); - void shrink(size_t bytes); // Accessing spaces - ContiguousSpace* the_space() const { return _the_space; } + ContiguousSpace* space() const { return _the_space; } + void assert_correct_size_change_locking(); public: TenuredGeneration(ReservedSpace rs, size_t initial_byte_size, int level, GenRemSet* remset); @@ -81,33 +72,15 @@ class TenuredGeneration: public CardGeneration { return !ScavengeBeforeFullGC; } - inline bool is_in(const void* p) const; - - // Space enquiries - size_t capacity() const; - size_t used() const; - size_t free() const; - - MemRegion used_region() const; - size_t unsafe_max_alloc_nogc() const; size_t contiguous_available() const; // Iteration void object_iterate(ObjectClosure* blk); - void space_iterate(SpaceClosure* blk, bool usedOnly = false); - - void younger_refs_iterate(OopsInGenClosure* blk); - - inline CompactibleSpace* first_compaction_space() const; virtual inline HeapWord* allocate(size_t word_size, bool is_tlab); virtual inline HeapWord* par_allocate(size_t word_size, bool is_tlab); - // Accessing marks - inline WaterMark top_mark(); - inline WaterMark bottom_mark(); - #define TenuredGen_SINCE_SAVE_MARKS_DECL(OopClosureType, nv_suffix) \ void oop_since_save_marks_iterate##nv_suffix(OopClosureType* cl); TenuredGen_SINCE_SAVE_MARKS_DECL(OopsInGenClosure,_v) diff --git a/hotspot/src/share/vm/memory/tenuredGeneration.inline.hpp b/hotspot/src/share/vm/memory/tenuredGeneration.inline.hpp index 0aa4c6d2d3b..aea97ea317a 100644 --- a/hotspot/src/share/vm/memory/tenuredGeneration.inline.hpp +++ b/hotspot/src/share/vm/memory/tenuredGeneration.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2010, 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 @@ -22,53 +22,35 @@ * */ -#ifndef SHARE_VM_MEMORY_GENERATION_INLINE_HPP -#define SHARE_VM_MEMORY_GENERATION_INLINE_HPP +#ifndef SHARE_VM_MEMORY_TENUREDGENERATION_INLINE_HPP +#define SHARE_VM_MEMORY_TENUREDGENERATION_INLINE_HPP -#include "memory/genCollectedHeap.hpp" #include "memory/space.hpp" #include "memory/tenuredGeneration.hpp" -bool TenuredGeneration::is_in(const void* p) const { - return the_space()->is_in(p); -} - - -WaterMark TenuredGeneration::top_mark() { - return the_space()->top_mark(); -} - -CompactibleSpace* -TenuredGeneration::first_compaction_space() const { - return the_space(); -} - HeapWord* TenuredGeneration::allocate(size_t word_size, bool is_tlab) { assert(!is_tlab, "TenuredGeneration does not support TLAB allocation"); - return the_space()->allocate(word_size); + return _the_space->allocate(word_size); } HeapWord* TenuredGeneration::par_allocate(size_t word_size, bool is_tlab) { assert(!is_tlab, "TenuredGeneration does not support TLAB allocation"); - return the_space()->par_allocate(word_size); -} - -WaterMark TenuredGeneration::bottom_mark() { - return the_space()->bottom_mark(); + return _the_space->par_allocate(word_size); } size_t TenuredGeneration::block_size(const HeapWord* addr) const { - if (addr < the_space()->top()) return oop(addr)->size(); - else { - assert(addr == the_space()->top(), "non-block head arg to block_size"); - return the_space()->end() - the_space()->top(); + if (addr < _the_space->top()) { + return oop(addr)->size(); + } else { + assert(addr == _the_space->top(), "non-block head arg to block_size"); + return _the_space->end() - _the_space->top(); } } bool TenuredGeneration::block_is_obj(const HeapWord* addr) const { - return addr < the_space()->top(); + return addr < _the_space ->top(); } -#endif // SHARE_VM_MEMORY_GENERATION_INLINE_HPP +#endif // SHARE_VM_MEMORY_TENUREDGENERATION_INLINE_HPP diff --git a/hotspot/src/share/vm/memory/universe.cpp b/hotspot/src/share/vm/memory/universe.cpp index c731140cd5f..61396a28c2b 100644 --- a/hotspot/src/share/vm/memory/universe.cpp +++ b/hotspot/src/share/vm/memory/universe.cpp @@ -120,6 +120,7 @@ oop Universe::_out_of_memory_error_metaspace = NULL; oop Universe::_out_of_memory_error_class_metaspace = NULL; oop Universe::_out_of_memory_error_array_size = NULL; oop Universe::_out_of_memory_error_gc_overhead_limit = NULL; +oop Universe::_out_of_memory_error_realloc_objects = NULL; objArrayOop Universe::_preallocated_out_of_memory_error_array = NULL; volatile jint Universe::_preallocated_out_of_memory_error_avail_count = 0; bool Universe::_verify_in_progress = false; @@ -191,6 +192,7 @@ void Universe::oops_do(OopClosure* f, bool do_all) { f->do_oop((oop*)&_out_of_memory_error_class_metaspace); f->do_oop((oop*)&_out_of_memory_error_array_size); f->do_oop((oop*)&_out_of_memory_error_gc_overhead_limit); + f->do_oop((oop*)&_out_of_memory_error_realloc_objects); f->do_oop((oop*)&_preallocated_out_of_memory_error_array); f->do_oop((oop*)&_null_ptr_exception_instance); f->do_oop((oop*)&_arithmetic_exception_instance); @@ -575,7 +577,8 @@ bool Universe::should_fill_in_stack_trace(Handle throwable) { (throwable() != Universe::_out_of_memory_error_metaspace) && (throwable() != Universe::_out_of_memory_error_class_metaspace) && (throwable() != Universe::_out_of_memory_error_array_size) && - (throwable() != Universe::_out_of_memory_error_gc_overhead_limit)); + (throwable() != Universe::_out_of_memory_error_gc_overhead_limit) && + (throwable() != Universe::_out_of_memory_error_realloc_objects)); } @@ -1039,6 +1042,7 @@ bool universe_post_init() { Universe::_out_of_memory_error_array_size = k_h->allocate_instance(CHECK_false); Universe::_out_of_memory_error_gc_overhead_limit = k_h->allocate_instance(CHECK_false); + Universe::_out_of_memory_error_realloc_objects = k_h->allocate_instance(CHECK_false); // Setup preallocated NullPointerException // (this is currently used for a cheap & dirty solution in compiler exception handling) @@ -1078,6 +1082,9 @@ bool universe_post_init() { msg = java_lang_String::create_from_str("GC overhead limit exceeded", CHECK_false); java_lang_Throwable::set_message(Universe::_out_of_memory_error_gc_overhead_limit, msg()); + msg = java_lang_String::create_from_str("Java heap space: failed reallocation of scalar replaced objects", CHECK_false); + java_lang_Throwable::set_message(Universe::_out_of_memory_error_realloc_objects, msg()); + msg = java_lang_String::create_from_str("/ by zero", CHECK_false); java_lang_Throwable::set_message(Universe::_arithmetic_exception_instance, msg()); diff --git a/hotspot/src/share/vm/memory/universe.hpp b/hotspot/src/share/vm/memory/universe.hpp index 40e2d03b6d4..52334d0dbce 100644 --- a/hotspot/src/share/vm/memory/universe.hpp +++ b/hotspot/src/share/vm/memory/universe.hpp @@ -157,6 +157,7 @@ class Universe: AllStatic { static oop _out_of_memory_error_class_metaspace; static oop _out_of_memory_error_array_size; static oop _out_of_memory_error_gc_overhead_limit; + static oop _out_of_memory_error_realloc_objects; static Array* _the_empty_int_array; // Canonicalized int array static Array* _the_empty_short_array; // Canonicalized short array @@ -328,6 +329,7 @@ class Universe: AllStatic { static oop out_of_memory_error_class_metaspace() { return gen_out_of_memory_error(_out_of_memory_error_class_metaspace); } static oop out_of_memory_error_array_size() { return gen_out_of_memory_error(_out_of_memory_error_array_size); } static oop out_of_memory_error_gc_overhead_limit() { return gen_out_of_memory_error(_out_of_memory_error_gc_overhead_limit); } + static oop out_of_memory_error_realloc_objects() { return gen_out_of_memory_error(_out_of_memory_error_realloc_objects); } // Accessors needed for fast allocation static Klass** boolArrayKlassObj_addr() { return &_boolArrayKlassObj; } diff --git a/hotspot/src/share/vm/oops/cpCache.cpp b/hotspot/src/share/vm/oops/cpCache.cpp index 64f16f78467..02c642f13a4 100644 --- a/hotspot/src/share/vm/oops/cpCache.cpp +++ b/hotspot/src/share/vm/oops/cpCache.cpp @@ -287,9 +287,13 @@ void ConstantPoolCacheEntry::set_method_handle_common(constantPoolHandle cpool, // the lock, so that when the losing writer returns, he can use the linked // cache entry. - // Use the lock from the metaspace for this, which cannot stop for safepoint. - Mutex* metaspace_lock = cpool->pool_holder()->class_loader_data()->metaspace_lock(); - MutexLockerEx ml(metaspace_lock, Mutex::_no_safepoint_check_flag); + objArrayHandle resolved_references = cpool->resolved_references(); + // Use the resolved_references() lock for this cpCache entry. + // resolved_references are created for all classes with Invokedynamic, MethodHandle + // or MethodType constant pool cache entries. + assert(resolved_references() != NULL, + "a resolved_references array should have been created for this class"); + ObjectLocker ol(resolved_references, Thread::current()); if (!is_f1_null()) { return; } @@ -336,7 +340,6 @@ void ConstantPoolCacheEntry::set_method_handle_common(constantPoolHandle cpool, // This allows us to create fewer Methods, while keeping type safety. // - objArrayHandle resolved_references = cpool->resolved_references(); // Store appendix, if any. if (has_appendix) { const int appendix_index = f2_as_index() + _indy_resolved_references_appendix_offset; diff --git a/hotspot/src/share/vm/opto/callnode.cpp b/hotspot/src/share/vm/opto/callnode.cpp index 619b37260b5..8268c97886c 100644 --- a/hotspot/src/share/vm/opto/callnode.cpp +++ b/hotspot/src/share/vm/opto/callnode.cpp @@ -658,7 +658,7 @@ void CallNode::dump_req(outputStream *st) const { void CallNode::dump_spec(outputStream *st) const { st->print(" "); - tf()->dump_on(st); + if (tf() != NULL) tf()->dump_on(st); if (_cnt != COUNT_UNKNOWN) st->print(" C=%f",_cnt); if (jvms() != NULL) jvms()->dump_spec(st); } diff --git a/hotspot/src/share/vm/opto/castnode.cpp b/hotspot/src/share/vm/opto/castnode.cpp index 3f3c5cab2ed..48aab726417 100644 --- a/hotspot/src/share/vm/opto/castnode.cpp +++ b/hotspot/src/share/vm/opto/castnode.cpp @@ -104,7 +104,8 @@ const Type *CastIINode::Value(PhaseTransform *phase) const { // Try to improve the type of the CastII if we recognize a CmpI/If // pattern. if (_carry_dependency) { - if (in(0) != NULL && (in(0)->is_IfFalse() || in(0)->is_IfTrue())) { + if (in(0) != NULL && in(0)->in(0) != NULL && in(0)->in(0)->is_If()) { + assert(in(0)->is_IfFalse() || in(0)->is_IfTrue(), "should be If proj"); Node* proj = in(0); if (proj->in(0)->in(1)->is_Bool()) { Node* b = proj->in(0)->in(1); diff --git a/hotspot/src/share/vm/opto/ifnode.cpp b/hotspot/src/share/vm/opto/ifnode.cpp index c0080c81d57..7b5f0d7b4be 100644 --- a/hotspot/src/share/vm/opto/ifnode.cpp +++ b/hotspot/src/share/vm/opto/ifnode.cpp @@ -820,6 +820,11 @@ static Node *remove_useless_bool(IfNode *iff, PhaseGVN *phase) { static IfNode* idealize_test(PhaseGVN* phase, IfNode* iff); +struct RangeCheck { + Node* ctl; + jint off; +}; + //------------------------------Ideal------------------------------------------ // Return a node which is more "ideal" than the current node. Strip out // control copies @@ -861,83 +866,141 @@ Node *IfNode::Ideal(PhaseGVN *phase, bool can_reshape) { jint offset1; int flip1 = is_range_check(range1, index1, offset1); if( flip1 ) { - Node *first_prev_dom = NULL; - // Try to remove extra range checks. All 'up_one_dom' gives up at merges // so all checks we inspect post-dominate the top-most check we find. // If we are going to fail the current check and we reach the top check // then we are guaranteed to fail, so just start interpreting there. - // We 'expand' the top 2 range checks to include all post-dominating + // We 'expand' the top 3 range checks to include all post-dominating // checks. - // The top 2 range checks seen - Node *prev_chk1 = NULL; - Node *prev_chk2 = NULL; + // The top 3 range checks seen + const int NRC =3; + RangeCheck prev_checks[NRC]; + int nb_checks = 0; + // Low and high offsets seen so far jint off_lo = offset1; jint off_hi = offset1; - // Scan for the top 2 checks and collect range of offsets - for( int dist = 0; dist < 999; dist++ ) { // Range-Check scan limit - if( dom->Opcode() == Op_If && // Not same opcode? - prev_dom->in(0) == dom ) { // One path of test does dominate? - if( dom == this ) return NULL; // dead loop + bool found_immediate_dominator = false; + + // Scan for the top checks and collect range of offsets + for (int dist = 0; dist < 999; dist++) { // Range-Check scan limit + if (dom->Opcode() == Op_If && // Not same opcode? + prev_dom->in(0) == dom) { // One path of test does dominate? + if (dom == this) return NULL; // dead loop // See if this is a range check Node *index2, *range2; jint offset2; int flip2 = dom->as_If()->is_range_check(range2, index2, offset2); // See if this is a _matching_ range check, checking against // the same array bounds. - if( flip2 == flip1 && range2 == range1 && index2 == index1 && - dom->outcnt() == 2 ) { + if (flip2 == flip1 && range2 == range1 && index2 == index1 && + dom->outcnt() == 2) { + if (nb_checks == 0 && dom->in(1) == in(1)) { + // Found an immediately dominating test at the same offset. + // This kind of back-to-back test can be eliminated locally, + // and there is no need to search further for dominating tests. + assert(offset2 == offset1, "Same test but different offsets"); + found_immediate_dominator = true; + break; + } // Gather expanded bounds off_lo = MIN2(off_lo,offset2); off_hi = MAX2(off_hi,offset2); - // Record top 2 range checks - prev_chk2 = prev_chk1; - prev_chk1 = prev_dom; - // If we match the test exactly, then the top test covers - // both our lower and upper bounds. - if( dom->in(1) == in(1) ) - prev_chk2 = prev_chk1; + // Record top NRC range checks + prev_checks[nb_checks%NRC].ctl = prev_dom; + prev_checks[nb_checks%NRC].off = offset2; + nb_checks++; } } prev_dom = dom; - dom = up_one_dom( dom ); - if( !dom ) break; + dom = up_one_dom(dom); + if (!dom) break; } + if (!found_immediate_dominator) { + // Attempt to widen the dominating range check to cover some later + // ones. Since range checks "fail" by uncommon-trapping to the + // interpreter, widening a check can make us speculatively enter + // the interpreter. If we see range-check deopt's, do not widen! + if (!phase->C->allow_range_check_smearing()) return NULL; - // Attempt to widen the dominating range check to cover some later - // ones. Since range checks "fail" by uncommon-trapping to the - // interpreter, widening a check can make us speculative enter the - // interpreter. If we see range-check deopt's, do not widen! - if (!phase->C->allow_range_check_smearing()) return NULL; - - // Constant indices only need to check the upper bound. - // Non-constance indices must check both low and high. - if( index1 ) { - // Didn't find 2 prior covering checks, so cannot remove anything. - if( !prev_chk2 ) return NULL; - // 'Widen' the offsets of the 1st and 2nd covering check - adjust_check( prev_chk1, range1, index1, flip1, off_lo, igvn ); - // Do not call adjust_check twice on the same projection - // as the first call may have transformed the BoolNode to a ConI - if( prev_chk1 != prev_chk2 ) { - adjust_check( prev_chk2, range1, index1, flip1, off_hi, igvn ); - } - // Test is now covered by prior checks, dominate it out - prev_dom = prev_chk2; - } else { // Didn't find prior covering check, so cannot remove anything. - if( !prev_chk1 ) return NULL; - // 'Widen' the offset of the 1st and only covering check - adjust_check( prev_chk1, range1, index1, flip1, off_hi, igvn ); - // Test is now covered by prior checks, dominate it out - prev_dom = prev_chk1; + if (nb_checks == 0) { + return NULL; + } + // Constant indices only need to check the upper bound. + // Non-constant indices must check both low and high. + int chk0 = (nb_checks - 1) % NRC; + if (index1) { + if (nb_checks == 1) { + return NULL; + } else { + // If the top range check's constant is the min or max of + // all constants we widen the next one to cover the whole + // range of constants. + RangeCheck rc0 = prev_checks[chk0]; + int chk1 = (nb_checks - 2) % NRC; + RangeCheck rc1 = prev_checks[chk1]; + if (rc0.off == off_lo) { + adjust_check(rc1.ctl, range1, index1, flip1, off_hi, igvn); + prev_dom = rc1.ctl; + } else if (rc0.off == off_hi) { + adjust_check(rc1.ctl, range1, index1, flip1, off_lo, igvn); + prev_dom = rc1.ctl; + } else { + // If the top test's constant is not the min or max of all + // constants, we need 3 range checks. We must leave the + // top test unchanged because widening it would allow the + // accesses it protects to successfully read/write out of + // bounds. + if (nb_checks == 2) { + return NULL; + } + int chk2 = (nb_checks - 3) % NRC; + RangeCheck rc2 = prev_checks[chk2]; + // The top range check a+i covers interval: -a <= i < length-a + // The second range check b+i covers interval: -b <= i < length-b + if (rc1.off <= rc0.off) { + // if b <= a, we change the second range check to: + // -min_of_all_constants <= i < length-min_of_all_constants + // Together top and second range checks now cover: + // -min_of_all_constants <= i < length-a + // which is more restrictive than -b <= i < length-b: + // -b <= -min_of_all_constants <= i < length-a <= length-b + // The third check is then changed to: + // -max_of_all_constants <= i < length-max_of_all_constants + // so 2nd and 3rd checks restrict allowed values of i to: + // -min_of_all_constants <= i < length-max_of_all_constants + adjust_check(rc1.ctl, range1, index1, flip1, off_lo, igvn); + adjust_check(rc2.ctl, range1, index1, flip1, off_hi, igvn); + } else { + // if b > a, we change the second range check to: + // -max_of_all_constants <= i < length-max_of_all_constants + // Together top and second range checks now cover: + // -a <= i < length-max_of_all_constants + // which is more restrictive than -b <= i < length-b: + // -b < -a <= i < length-max_of_all_constants <= length-b + // The third check is then changed to: + // -max_of_all_constants <= i < length-max_of_all_constants + // so 2nd and 3rd checks restrict allowed values of i to: + // -min_of_all_constants <= i < length-max_of_all_constants + adjust_check(rc1.ctl, range1, index1, flip1, off_hi, igvn); + adjust_check(rc2.ctl, range1, index1, flip1, off_lo, igvn); + } + prev_dom = rc2.ctl; + } + } + } else { + RangeCheck rc0 = prev_checks[chk0]; + // 'Widen' the offset of the 1st and only covering check + adjust_check(rc0.ctl, range1, index1, flip1, off_hi, igvn); + // Test is now covered by prior checks, dominate it out + prev_dom = rc0.ctl; + } } - } else { // Scan for an equivalent test Node *cmp; @@ -1019,7 +1082,7 @@ void IfNode::dominated_by( Node *prev_dom, PhaseIterGVN *igvn ) { // for lower and upper bounds. ProjNode* unc_proj = proj_out(1 - prev_dom->as_Proj()->_con)->as_Proj(); if (unc_proj->is_uncommon_trap_proj(Deoptimization::Reason_predicate)) - prev_dom = idom; + prev_dom = idom; // Now walk the current IfNode's projections. // Loop ends when 'this' has no more uses. diff --git a/hotspot/src/share/vm/opto/lcm.cpp b/hotspot/src/share/vm/opto/lcm.cpp index a601752d4cd..3aab19fc52e 100644 --- a/hotspot/src/share/vm/opto/lcm.cpp +++ b/hotspot/src/share/vm/opto/lcm.cpp @@ -417,8 +417,15 @@ void PhaseCFG::implicit_null_check(Block* block, Node *proj, Node *val, int allo for (DUIterator_Last i2min, i2 = old_tst->last_outs(i2min); i2 >= i2min; --i2) old_tst->last_out(i2)->set_req(0, nul_chk); // Clean-up any dead code - for (uint i3 = 0; i3 < old_tst->req(); i3++) + for (uint i3 = 0; i3 < old_tst->req(); i3++) { + Node* in = old_tst->in(i3); old_tst->set_req(i3, NULL); + if (in->outcnt() == 0) { + // Remove dead input node + in->disconnect_inputs(NULL, C); + block->find_remove(in); + } + } latency_from_uses(nul_chk); latency_from_uses(best); diff --git a/hotspot/src/share/vm/opto/loopnode.cpp b/hotspot/src/share/vm/opto/loopnode.cpp index 5ca0ab059db..e3667964668 100644 --- a/hotspot/src/share/vm/opto/loopnode.cpp +++ b/hotspot/src/share/vm/opto/loopnode.cpp @@ -1147,7 +1147,7 @@ const TypeInt* PhaseIdealLoop::filtered_type_from_dominators( Node* val, Node *u // Dump special per-node info #ifndef PRODUCT void CountedLoopEndNode::dump_spec(outputStream *st) const { - if( in(TestValue)->is_Bool() ) { + if( in(TestValue) != NULL && in(TestValue)->is_Bool() ) { BoolTest bt( test_trip()); // Added this for g++. st->print("["); diff --git a/hotspot/src/share/vm/opto/loopopts.cpp b/hotspot/src/share/vm/opto/loopopts.cpp index bfa483c0181..e00a47dbfda 100644 --- a/hotspot/src/share/vm/opto/loopopts.cpp +++ b/hotspot/src/share/vm/opto/loopopts.cpp @@ -241,8 +241,13 @@ void PhaseIdealLoop::dominated_by( Node *prevdom, Node *iff, bool flip, bool exc ProjNode* dp_proj = dp->as_Proj(); ProjNode* unc_proj = iff->as_If()->proj_out(1 - dp_proj->_con)->as_Proj(); if (exclude_loop_predicate && - unc_proj->is_uncommon_trap_proj(Deoptimization::Reason_predicate)) + (unc_proj->is_uncommon_trap_proj(Deoptimization::Reason_predicate) || + unc_proj->is_uncommon_trap_proj(Deoptimization::Reason_range_check))) { + // If this is a range check (IfNode::is_range_check), do not + // reorder because Compile::allow_range_check_smearing might have + // changed the check. return; // Let IGVN transformation change control dependence. + } IdealLoopTree *old_loop = get_loop(dp); @@ -898,23 +903,23 @@ void PhaseIdealLoop::split_if_with_blocks_post( Node *n ) { int n_op = n->Opcode(); // Check for an IF being dominated by another IF same test - if( n_op == Op_If ) { + if (n_op == Op_If) { Node *bol = n->in(1); uint max = bol->outcnt(); // Check for same test used more than once? - if( n_op == Op_If && max > 1 && bol->is_Bool() ) { + if (max > 1 && bol->is_Bool()) { // Search up IDOMs to see if this IF is dominated. Node *cutoff = get_ctrl(bol); // Now search up IDOMs till cutoff, looking for a dominating test Node *prevdom = n; Node *dom = idom(prevdom); - while( dom != cutoff ) { - if( dom->req() > 1 && dom->in(1) == bol && prevdom->in(0) == dom ) { + while (dom != cutoff) { + if (dom->req() > 1 && dom->in(1) == bol && prevdom->in(0) == dom) { // Replace the dominated test with an obvious true or false. // Place it on the IGVN worklist for later cleanup. C->set_major_progress(); - dominated_by( prevdom, n, false, true ); + dominated_by(prevdom, n, false, true); #ifndef PRODUCT if( VerifyLoopOptimizations ) verify(); #endif diff --git a/hotspot/src/share/vm/opto/machnode.cpp b/hotspot/src/share/vm/opto/machnode.cpp index 39c30782936..cd809abb5f8 100644 --- a/hotspot/src/share/vm/opto/machnode.cpp +++ b/hotspot/src/share/vm/opto/machnode.cpp @@ -473,8 +473,13 @@ bool MachNode::rematerialize() const { // Print any per-operand special info void MachNode::dump_spec(outputStream *st) const { uint cnt = num_opnds(); - for( uint i=0; idump_spec(st); + for( uint i=0; idump_spec(st); + } else { + st->print(" _"); + } + } const TypePtr *t = adr_type(); if( t ) { Compile* C = Compile::current(); @@ -493,7 +498,11 @@ void MachNode::dump_format(PhaseRegAlloc *ra, outputStream *st) const { //============================================================================= #ifndef PRODUCT void MachTypeNode::dump_spec(outputStream *st) const { - _bottom_type->dump_on(st); + if (_bottom_type != NULL) { + _bottom_type->dump_on(st); + } else { + st->print(" NULL"); + } } #endif @@ -635,7 +644,7 @@ const Type *MachCallNode::Value(PhaseTransform *phase) const { return tf()->rang #ifndef PRODUCT void MachCallNode::dump_spec(outputStream *st) const { st->print("# "); - tf()->dump_on(st); + if (tf() != NULL) tf()->dump_on(st); if (_cnt != COUNT_UNKNOWN) st->print(" C=%f",_cnt); if (jvms() != NULL) jvms()->dump_spec(st); } diff --git a/hotspot/src/share/vm/opto/macro.cpp b/hotspot/src/share/vm/opto/macro.cpp index 073945c833d..b393745620b 100644 --- a/hotspot/src/share/vm/opto/macro.cpp +++ b/hotspot/src/share/vm/opto/macro.cpp @@ -971,7 +971,11 @@ void PhaseMacroExpand::process_users_of_allocation(CallNode *alloc) { } bool PhaseMacroExpand::eliminate_allocate_node(AllocateNode *alloc) { - if (!EliminateAllocations || !alloc->_is_non_escaping) { + // Don't do scalar replacement if the frame can be popped by JVMTI: + // if reallocation fails during deoptimization we'll pop all + // interpreter frames for this compiled frame and that won't play + // nice with JVMTI popframe. + if (!EliminateAllocations || JvmtiExport::can_pop_frame() || !alloc->_is_non_escaping) { return false; } Node* klass = alloc->in(AllocateNode::KlassNode); diff --git a/hotspot/src/share/vm/opto/memnode.cpp b/hotspot/src/share/vm/opto/memnode.cpp index 702cc9bbd7e..966bcbeb0f7 100644 --- a/hotspot/src/share/vm/opto/memnode.cpp +++ b/hotspot/src/share/vm/opto/memnode.cpp @@ -4370,7 +4370,7 @@ void MergeMemNode::dump_spec(outputStream *st) const { st->print(" {"); Node* base_mem = base_memory(); for( uint i = Compile::AliasIdxRaw; i < req(); i++ ) { - Node* mem = memory_at(i); + Node* mem = (in(i) != NULL) ? memory_at(i) : base_mem; if (mem == base_mem) { st->print(" -"); continue; } st->print( " N%d:", mem->_idx ); Compile::current()->get_adr_type(i)->dump_on(st); diff --git a/hotspot/src/share/vm/prims/jvm.cpp b/hotspot/src/share/vm/prims/jvm.cpp index 2c37471d97d..a94242a64a1 100644 --- a/hotspot/src/share/vm/prims/jvm.cpp +++ b/hotspot/src/share/vm/prims/jvm.cpp @@ -700,23 +700,7 @@ JVM_END // Returns a class loaded by the bootstrap class loader; or null // if not found. ClassNotFoundException is not thrown. -// -// Rationale behind JVM_FindClassFromBootLoader -// a> JVM_FindClassFromClassLoader was never exported in the export tables. -// b> because of (a) java.dll has a direct dependecy on the unexported -// private symbol "_JVM_FindClassFromClassLoader@20". -// c> the launcher cannot use the private symbol as it dynamically opens -// the entry point, so if something changes, the launcher will fail -// unexpectedly at runtime, it is safest for the launcher to dlopen a -// stable exported interface. -// d> re-exporting JVM_FindClassFromClassLoader as public, will cause its -// signature to change from _JVM_FindClassFromClassLoader@20 to -// JVM_FindClassFromClassLoader and will not be backward compatible -// with older JDKs. -// Thus a public/stable exported entry point is the right solution, -// public here means public in linker semantics, and is exported only -// to the JDK, and is not intended to be a public API. - +// FindClassFromBootLoader is exported to the launcher for windows. JVM_ENTRY(jclass, JVM_FindClassFromBootLoader(JNIEnv* env, const char* name)) JVMWrapper2("JVM_FindClassFromBootLoader %s", name); @@ -740,33 +724,6 @@ JVM_ENTRY(jclass, JVM_FindClassFromBootLoader(JNIEnv* env, 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)) - JVMWrapper3("JVM_FindClassFromClassLoader %s throw %s", name, - throwError ? "error" : "exception"); - // 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. - if (throwError) { - THROW_MSG_0(vmSymbols::java_lang_NoClassDefFoundError(), name); - } else { - THROW_MSG_0(vmSymbols::java_lang_ClassNotFoundException(), name); - } - } - TempNewSymbol h_name = SymbolTable::new_symbol(name, CHECK_NULL); - Handle h_loader(THREAD, JNIHandles::resolve(loader)); - jclass result = find_class_from_class_loader(env, h_name, init, h_loader, - Handle(), throwError, THREAD); - - if (TraceClassResolution && result != NULL) { - trace_class_resolution(java_lang_Class::as_Klass(JNIHandles::resolve_non_null(result))); - } - 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, diff --git a/hotspot/src/share/vm/prims/jvm.h b/hotspot/src/share/vm/prims/jvm.h index f3b045c9521..81faa7197d1 100644 --- a/hotspot/src/share/vm/prims/jvm.h +++ b/hotspot/src/share/vm/prims/jvm.h @@ -334,15 +334,6 @@ JVM_GetCallerClass(JNIEnv *env, int n); JNIEXPORT jclass JNICALL JVM_FindPrimitiveClass(JNIEnv *env, const char *utf); -/* - * Find a class from a given class loader. Throw ClassNotFoundException - * or NoClassDefFoundError depending on the value of the last - * argument. - */ -JNIEXPORT jclass JNICALL -JVM_FindClassFromClassLoader(JNIEnv *env, const char *name, jboolean init, - jobject loader, jboolean throwError); - /* * Find a class from a boot class loader. Returns NULL if class not found. */ diff --git a/hotspot/src/share/vm/prims/whitebox.cpp b/hotspot/src/share/vm/prims/whitebox.cpp index 93cad0884d2..afde0ae63e1 100644 --- a/hotspot/src/share/vm/prims/whitebox.cpp +++ b/hotspot/src/share/vm/prims/whitebox.cpp @@ -69,6 +69,14 @@ PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC bool WhiteBox::_used = false; volatile bool WhiteBox::compilation_locked = false; +class VM_WhiteBoxOperation : public VM_Operation { + public: + VM_WhiteBoxOperation() { } + VMOp_Type type() const { return VMOp_WhiteBoxOperation; } + bool allow_nested_vm_operations() const { return true; } +}; + + WB_ENTRY(jlong, WB_GetObjectAddress(JNIEnv* env, jobject o, jobject obj)) return (jlong)(void*)JNIHandles::resolve(obj); WB_END @@ -404,6 +412,43 @@ static jmethodID reflected_method_to_jmid(JavaThread* thread, JNIEnv* env, jobje return env->FromReflectedMethod(method); } +// Deoptimizes all compiled frames and makes nmethods not entrant if it's requested +class VM_WhiteBoxDeoptimizeFrames : public VM_WhiteBoxOperation { + private: + int _result; + const bool _make_not_entrant; + public: + VM_WhiteBoxDeoptimizeFrames(bool make_not_entrant) : + _result(0), _make_not_entrant(make_not_entrant) { } + int result() const { return _result; } + + void doit() { + for (JavaThread* t = Threads::first(); t != NULL; t = t->next()) { + if (t->has_last_Java_frame()) { + for (StackFrameStream fst(t, UseBiasedLocking); !fst.is_done(); fst.next()) { + frame* f = fst.current(); + if (f->can_be_deoptimized() && !f->is_deoptimized_frame()) { + RegisterMap* reg_map = fst.register_map(); + Deoptimization::deoptimize(t, *f, reg_map); + if (_make_not_entrant) { + nmethod* nm = CodeCache::find_nmethod(f->pc()); + assert(nm != NULL, "sanity check"); + nm->make_not_entrant(); + } + ++_result; + } + } + } + } + } +}; + +WB_ENTRY(jint, WB_DeoptimizeFrames(JNIEnv* env, jobject o, jboolean make_not_entrant)) + VM_WhiteBoxDeoptimizeFrames op(make_not_entrant == JNI_TRUE); + VMThread::execute(&op); + return op.result(); +WB_END + WB_ENTRY(void, WB_DeoptimizeAll(JNIEnv* env, jobject o)) MutexLockerEx mu(Compile_lock); CodeCache::mark_all_nmethods_for_deoptimization(); @@ -526,13 +571,6 @@ WB_ENTRY(jboolean, WB_EnqueueMethodForCompilation(JNIEnv* env, jobject o, jobjec return (mh->queued_for_compilation() || nm != NULL); WB_END -class VM_WhiteBoxOperation : public VM_Operation { - public: - VM_WhiteBoxOperation() { } - VMOp_Type type() const { return VMOp_WhiteBoxOperation; } - bool allow_nested_vm_operations() const { return true; } -}; - class AlwaysFalseClosure : public BoolObjectClosure { public: bool do_object_b(oop p) { return false; } @@ -761,7 +799,6 @@ WB_ENTRY(void, WB_SetStringVMFlag(JNIEnv* env, jobject o, jstring name, jstring } WB_END - WB_ENTRY(void, WB_LockCompilation(JNIEnv* env, jobject o, jlong timeout)) WhiteBox::compilation_locked = true; WB_END @@ -1078,6 +1115,14 @@ WB_ENTRY(jlong, WB_MetaspaceCapacityUntilGC(JNIEnv* env, jobject wb)) return (jlong) MetaspaceGC::capacity_until_GC(); WB_END +WB_ENTRY(void, WB_AssertMatchingSafepointCalls(JNIEnv* env, jobject o, jboolean mutexSafepointValue, jboolean attemptedNoSafepointValue)) + Monitor::SafepointCheckRequired sfpt_check_required = mutexSafepointValue ? + Monitor::_safepoint_check_always : + Monitor::_safepoint_check_never; + MutexLockerEx ml(new Mutex(Mutex::leaf, "SFPT_Test_lock", true, sfpt_check_required), + attemptedNoSafepointValue == JNI_TRUE); +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) { @@ -1201,6 +1246,7 @@ static JNINativeMethod methods[] = { {CC"NMTChangeTrackingLevel", CC"()Z", (void*)&WB_NMTChangeTrackingLevel}, {CC"NMTGetHashSize", CC"()I", (void*)&WB_NMTGetHashSize }, #endif // INCLUDE_NMT + {CC"deoptimizeFrames", CC"(Z)I", (void*)&WB_DeoptimizeFrames }, {CC"deoptimizeAll", CC"()V", (void*)&WB_DeoptimizeAll }, {CC"deoptimizeMethod", CC"(Ljava/lang/reflect/Executable;Z)I", (void*)&WB_DeoptimizeMethod }, @@ -1274,6 +1320,7 @@ static JNINativeMethod methods[] = { {CC"getCodeBlob", CC"(J)[Ljava/lang/Object;",(void*)&WB_GetCodeBlob }, {CC"getThreadStackSize", CC"()J", (void*)&WB_GetThreadStackSize }, {CC"getThreadRemainingStackSize", CC"()J", (void*)&WB_GetThreadRemainingStackSize }, + {CC"assertMatchingSafepointCalls", CC"(ZZ)V", (void*)&WB_AssertMatchingSafepointCalls }, }; #undef CC diff --git a/hotspot/src/share/vm/prims/whitebox.hpp b/hotspot/src/share/vm/prims/whitebox.hpp index 4ead33f7fec..59754270e35 100644 --- a/hotspot/src/share/vm/prims/whitebox.hpp +++ b/hotspot/src/share/vm/prims/whitebox.hpp @@ -74,7 +74,7 @@ class WhiteBox : public AllStatic { static JavaThread* create_sweeper_thread(TRAPS); static int get_blob_type(const CodeBlob* code); static CodeHeap* get_code_heap(int blob_type); - static CodeBlob* allocate_code_blob(int blob_type, int size); + static CodeBlob* allocate_code_blob(int size, int blob_type); static int array_bytes_to_length(size_t bytes); static void register_methods(JNIEnv* env, jclass wbclass, JavaThread* thread, JNINativeMethod* method_array, int method_count); diff --git a/hotspot/src/share/vm/runtime/arguments.cpp b/hotspot/src/share/vm/runtime/arguments.cpp index d3dcac3c2b0..57ec22b81c3 100644 --- a/hotspot/src/share/vm/runtime/arguments.cpp +++ b/hotspot/src/share/vm/runtime/arguments.cpp @@ -125,8 +125,8 @@ char* Arguments::_meta_index_path = NULL; char* Arguments::_meta_index_dir = NULL; char* Arguments::_ext_dirs = NULL; -// Check if head of 'option' matches 'name', and sets 'tail' remaining part of option string - +// Check if head of 'option' matches 'name', and sets 'tail' to the remaining +// part of the option string. static bool match_option(const JavaVMOption *option, const char* name, const char** tail) { int len = (int)strlen(name); @@ -138,6 +138,32 @@ static bool match_option(const JavaVMOption *option, const char* name, } } +// Check if 'option' matches 'name'. No "tail" is allowed. +static bool match_option(const JavaVMOption *option, const char* name) { + const char* tail = NULL; + bool result = match_option(option, name, &tail); + if (tail != NULL && *tail == '\0') { + return result; + } else { + return false; + } +} + +// Return true if any of the strings in null-terminated array 'names' matches. +// If tail_allowed is true, then the tail must begin with a colon; otherwise, +// the option must match exactly. +static bool match_option(const JavaVMOption* option, const char** names, const char** tail, + bool tail_allowed) { + for (/* empty */; *names != NULL; ++names) { + if (match_option(option, *names, tail)) { + if (**tail == '\0' || tail_allowed && **tail == ':') { + return true; + } + } + } + return false; +} + static void logOption(const char* opt) { if (PrintVMOptions) { jio_fprintf(defaultStream::output_stream(), "VM option '%s'\n", opt); @@ -899,9 +925,9 @@ bool Arguments::process_argument(const char* arg, "Warning: support for %s was removed in %s\n", fuzzy_matched->_name, version); - } } } + } // allow for commandline "commenting out" options like -XX:#+Verbose return arg[0] == '#'; @@ -1356,41 +1382,24 @@ void Arguments::set_cms_and_parnew_gc_flags() { if (FLAG_IS_DEFAULT(SurvivorRatio) && MaxTenuringThreshold == 0) { FLAG_SET_ERGO(uintx, SurvivorRatio, MAX2((uintx)1024, SurvivorRatio)); } - // If OldPLABSize is set and CMSParPromoteBlocksToClaim is not, - // set CMSParPromoteBlocksToClaim equal to OldPLABSize. - // This is done in order to make ParNew+CMS configuration to work - // with YoungPLABSize and OldPLABSize options. - // See CR 6362902. - if (!FLAG_IS_DEFAULT(OldPLABSize)) { - if (FLAG_IS_DEFAULT(CMSParPromoteBlocksToClaim)) { - // OldPLABSize is not the default value but CMSParPromoteBlocksToClaim - // is. In this situation let CMSParPromoteBlocksToClaim follow - // the value (either from the command line or ergonomics) of - // OldPLABSize. Following OldPLABSize is an ergonomics decision. - FLAG_SET_ERGO(uintx, CMSParPromoteBlocksToClaim, OldPLABSize); + + // OldPLABSize is interpreted in CMS as not the size of the PLAB in words, + // but rather the number of free blocks of a given size that are used when + // replenishing the local per-worker free list caches. + if (FLAG_IS_DEFAULT(OldPLABSize)) { + if (!FLAG_IS_DEFAULT(ResizeOldPLAB) && !ResizeOldPLAB) { + // OldPLAB sizing manually turned off: Use a larger default setting, + // unless it was manually specified. This is because a too-low value + // will slow down scavenges. + FLAG_SET_ERGO(uintx, OldPLABSize, CFLS_LAB::_default_static_old_plab_size); // default value before 6631166 } else { - // OldPLABSize and CMSParPromoteBlocksToClaim are both set. - // CMSParPromoteBlocksToClaim is a collector-specific flag, so - // we'll let it to take precedence. - jio_fprintf(defaultStream::error_stream(), - "Both OldPLABSize and CMSParPromoteBlocksToClaim" - " options are specified for the CMS collector." - " CMSParPromoteBlocksToClaim will take precedence.\n"); + FLAG_SET_DEFAULT(OldPLABSize, CFLS_LAB::_default_dynamic_old_plab_size); // old CMSParPromoteBlocksToClaim default } } - if (!FLAG_IS_DEFAULT(ResizeOldPLAB) && !ResizeOldPLAB) { - // OldPLAB sizing manually turned off: Use a larger default setting, - // unless it was manually specified. This is because a too-low value - // will slow down scavenges. - if (FLAG_IS_DEFAULT(CMSParPromoteBlocksToClaim)) { - FLAG_SET_ERGO(uintx, CMSParPromoteBlocksToClaim, 50); // default value before 6631166 - } - } - // Overwrite OldPLABSize which is the variable we will internally use everywhere. - FLAG_SET_ERGO(uintx, OldPLABSize, CMSParPromoteBlocksToClaim); + // If either of the static initialization defaults have changed, note this // modification. - if (!FLAG_IS_DEFAULT(CMSParPromoteBlocksToClaim) || !FLAG_IS_DEFAULT(OldPLABWeight)) { + if (!FLAG_IS_DEFAULT(OldPLABSize) || !FLAG_IS_DEFAULT(OldPLABWeight)) { CFLS_LAB::modify_initialization(OldPLABSize, OldPLABWeight); } if (PrintGCDetails && Verbose) { @@ -2526,21 +2535,6 @@ static const char* system_assertion_options[] = { "-dsa", "-esa", "-disablesystemassertions", "-enablesystemassertions", 0 }; -// Return true if any of the strings in null-terminated array 'names' matches. -// If tail_allowed is true, then the tail must begin with a colon; otherwise, -// the option must match exactly. -static bool match_option(const JavaVMOption* option, const char** names, const char** tail, - bool tail_allowed) { - for (/* empty */; *names != NULL; ++names) { - if (match_option(option, *names, tail)) { - if (**tail == '\0' || tail_allowed && **tail == ':') { - return true; - } - } - } - return false; -} - bool Arguments::parse_uintx(const char* value, uintx* uintx_arg, uintx min_size) { @@ -2782,16 +2776,16 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args, } #endif // !INCLUDE_JVMTI // -Xnoclassgc - } else if (match_option(option, "-Xnoclassgc", &tail)) { + } else if (match_option(option, "-Xnoclassgc")) { FLAG_SET_CMDLINE(bool, ClassUnloading, false); // -Xconcgc - } else if (match_option(option, "-Xconcgc", &tail)) { + } else if (match_option(option, "-Xconcgc")) { FLAG_SET_CMDLINE(bool, UseConcMarkSweepGC, true); // -Xnoconcgc - } else if (match_option(option, "-Xnoconcgc", &tail)) { + } else if (match_option(option, "-Xnoconcgc")) { FLAG_SET_CMDLINE(bool, UseConcMarkSweepGC, false); // -Xbatch - } else if (match_option(option, "-Xbatch", &tail)) { + } else if (match_option(option, "-Xbatch")) { FLAG_SET_CMDLINE(bool, BackgroundCompilation, false); // -Xmn for compatibility with other JVM vendors } else if (match_option(option, "-Xmn", &tail)) { @@ -2936,28 +2930,28 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args, } FLAG_SET_CMDLINE(uintx, IncreaseFirstTierCompileThresholdAt, (uintx)uint_IncreaseFirstTierCompileThresholdAt); // -green - } else if (match_option(option, "-green", &tail)) { + } else if (match_option(option, "-green")) { jio_fprintf(defaultStream::error_stream(), "Green threads support not available\n"); return JNI_EINVAL; // -native - } else if (match_option(option, "-native", &tail)) { + } else if (match_option(option, "-native")) { // HotSpot always uses native threads, ignore silently for compatibility // -Xsqnopause - } else if (match_option(option, "-Xsqnopause", &tail)) { + } else if (match_option(option, "-Xsqnopause")) { // EVM option, ignore silently for compatibility // -Xrs - } else if (match_option(option, "-Xrs", &tail)) { + } else if (match_option(option, "-Xrs")) { // Classic/EVM option, new functionality FLAG_SET_CMDLINE(bool, ReduceSignalUsage, true); - } else if (match_option(option, "-Xusealtsigs", &tail)) { + } else if (match_option(option, "-Xusealtsigs")) { // change default internal VM signals used - lower case for back compat FLAG_SET_CMDLINE(bool, UseAltSigs, true); // -Xoptimize - } else if (match_option(option, "-Xoptimize", &tail)) { + } else if (match_option(option, "-Xoptimize")) { // EVM option, ignore silently for compatibility // -Xprof - } else if (match_option(option, "-Xprof", &tail)) { + } else if (match_option(option, "-Xprof")) { #if INCLUDE_FPROF _has_profile = true; #else // INCLUDE_FPROF @@ -2966,7 +2960,7 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args, return JNI_ERR; #endif // INCLUDE_FPROF // -Xconcurrentio - } else if (match_option(option, "-Xconcurrentio", &tail)) { + } else if (match_option(option, "-Xconcurrentio")) { FLAG_SET_CMDLINE(bool, UseLWPSynchronization, true); FLAG_SET_CMDLINE(bool, BackgroundCompilation, false); FLAG_SET_CMDLINE(intx, DeferThrSuspendLoopCount, 1); @@ -2974,29 +2968,32 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args, FLAG_SET_CMDLINE(uintx, NewSizeThreadIncrease, 16 * K); // 20Kb per thread added to new generation // -Xinternalversion - } else if (match_option(option, "-Xinternalversion", &tail)) { + } else if (match_option(option, "-Xinternalversion")) { jio_fprintf(defaultStream::output_stream(), "%s\n", VM_Version::internal_vm_info_string()); vm_exit(0); #ifndef PRODUCT // -Xprintflags - } else if (match_option(option, "-Xprintflags", &tail)) { + } else if (match_option(option, "-Xprintflags")) { CommandLineFlags::printFlags(tty, false); vm_exit(0); #endif // -D } else if (match_option(option, "-D", &tail)) { - if (match_option(option, "-Djava.endorsed.dirs=", &tail)) { + const char* value; + if (match_option(option, "-Djava.endorsed.dirs=", &value) && + *value!= '\0' && strcmp(value, "\"\"") != 0) { // abort if -Djava.endorsed.dirs is set jio_fprintf(defaultStream::output_stream(), - "-Djava.endorsed.dirs is not supported. Endorsed standards and standalone APIs\n" - "in modular form will be supported via the concept of upgradeable modules.\n"); + "-Djava.endorsed.dirs=%s is not supported. Endorsed standards and standalone APIs\n" + "in modular form will be supported via the concept of upgradeable modules.\n", value); return JNI_EINVAL; } - if (match_option(option, "-Djava.ext.dirs=", &tail)) { + if (match_option(option, "-Djava.ext.dirs=", &value) && + *value != '\0' && strcmp(value, "\"\"") != 0) { // abort if -Djava.ext.dirs is set jio_fprintf(defaultStream::output_stream(), - "-Djava.ext.dirs is not supported. Use -classpath instead.\n"); + "-Djava.ext.dirs=%s is not supported. Use -classpath instead.\n", value); return JNI_EINVAL; } @@ -3014,29 +3011,29 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args, #endif } // -Xint - } else if (match_option(option, "-Xint", &tail)) { + } else if (match_option(option, "-Xint")) { set_mode_flags(_int); // -Xmixed - } else if (match_option(option, "-Xmixed", &tail)) { + } else if (match_option(option, "-Xmixed")) { set_mode_flags(_mixed); // -Xcomp - } else if (match_option(option, "-Xcomp", &tail)) { + } else if (match_option(option, "-Xcomp")) { // for testing the compiler; turn off all flags that inhibit compilation set_mode_flags(_comp); // -Xshare:dump - } else if (match_option(option, "-Xshare:dump", &tail)) { + } else if (match_option(option, "-Xshare:dump")) { FLAG_SET_CMDLINE(bool, DumpSharedSpaces, true); set_mode_flags(_int); // Prevent compilation, which creates objects // -Xshare:on - } else if (match_option(option, "-Xshare:on", &tail)) { + } else if (match_option(option, "-Xshare:on")) { FLAG_SET_CMDLINE(bool, UseSharedSpaces, true); FLAG_SET_CMDLINE(bool, RequireSharedSpaces, true); // -Xshare:auto - } else if (match_option(option, "-Xshare:auto", &tail)) { + } else if (match_option(option, "-Xshare:auto")) { FLAG_SET_CMDLINE(bool, UseSharedSpaces, true); FLAG_SET_CMDLINE(bool, RequireSharedSpaces, false); // -Xshare:off - } else if (match_option(option, "-Xshare:off", &tail)) { + } else if (match_option(option, "-Xshare:off")) { FLAG_SET_CMDLINE(bool, UseSharedSpaces, false); FLAG_SET_CMDLINE(bool, RequireSharedSpaces, false); // -Xverify @@ -3054,13 +3051,13 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args, return JNI_EINVAL; } // -Xdebug - } else if (match_option(option, "-Xdebug", &tail)) { + } else if (match_option(option, "-Xdebug")) { // note this flag has been used, then ignore set_xdebug_mode(true); // -Xnoagent - } else if (match_option(option, "-Xnoagent", &tail)) { + } else if (match_option(option, "-Xnoagent")) { // For compatibility with classic. HotSpot refuses to load the old style agent.dll. - } else if (match_option(option, "-Xboundthreads", &tail)) { + } else if (match_option(option, "-Xboundthreads")) { // Bind user level threads to kernel threads (Solaris only) FLAG_SET_CMDLINE(bool, UseBoundThreads, true); } else if (match_option(option, "-Xloggc:", &tail)) { @@ -3090,14 +3087,14 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args, "check")) { return JNI_EINVAL; } - } else if (match_option(option, "vfprintf", &tail)) { + } else if (match_option(option, "vfprintf")) { _vfprintf_hook = CAST_TO_FN_PTR(vfprintf_hook_t, option->extraInfo); - } else if (match_option(option, "exit", &tail)) { + } else if (match_option(option, "exit")) { _exit_hook = CAST_TO_FN_PTR(exit_hook_t, option->extraInfo); - } else if (match_option(option, "abort", &tail)) { + } else if (match_option(option, "abort")) { _abort_hook = CAST_TO_FN_PTR(abort_hook_t, option->extraInfo); // -XX:+AggressiveHeap - } else if (match_option(option, "-XX:+AggressiveHeap", &tail)) { + } else if (match_option(option, "-XX:+AggressiveHeap")) { // This option inspects the machine and attempts to set various // parameters to be optimal for long-running, memory allocation @@ -3188,11 +3185,11 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args, // Need to keep consistency of MaxTenuringThreshold and AlwaysTenure/NeverTenure; // and the last option wins. - } else if (match_option(option, "-XX:+NeverTenure", &tail)) { + } else if (match_option(option, "-XX:+NeverTenure")) { FLAG_SET_CMDLINE(bool, NeverTenure, true); FLAG_SET_CMDLINE(bool, AlwaysTenure, false); FLAG_SET_CMDLINE(uintx, MaxTenuringThreshold, markOopDesc::max_age + 1); - } else if (match_option(option, "-XX:+AlwaysTenure", &tail)) { + } else if (match_option(option, "-XX:+AlwaysTenure")) { FLAG_SET_CMDLINE(bool, NeverTenure, false); FLAG_SET_CMDLINE(bool, AlwaysTenure, true); FLAG_SET_CMDLINE(uintx, MaxTenuringThreshold, 0); @@ -3211,59 +3208,13 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args, FLAG_SET_CMDLINE(bool, NeverTenure, false); FLAG_SET_CMDLINE(bool, AlwaysTenure, false); } - } else if (match_option(option, "-XX:+CMSPermGenSweepingEnabled", &tail) || - match_option(option, "-XX:-CMSPermGenSweepingEnabled", &tail)) { - jio_fprintf(defaultStream::error_stream(), - "Please use CMSClassUnloadingEnabled in place of " - "CMSPermGenSweepingEnabled in the future\n"); - } else if (match_option(option, "-XX:+UseGCTimeLimit", &tail)) { - FLAG_SET_CMDLINE(bool, UseGCOverheadLimit, true); - jio_fprintf(defaultStream::error_stream(), - "Please use -XX:+UseGCOverheadLimit in place of " - "-XX:+UseGCTimeLimit in the future\n"); - } else if (match_option(option, "-XX:-UseGCTimeLimit", &tail)) { - FLAG_SET_CMDLINE(bool, UseGCOverheadLimit, false); - jio_fprintf(defaultStream::error_stream(), - "Please use -XX:-UseGCOverheadLimit in place of " - "-XX:-UseGCTimeLimit in the future\n"); - // The TLE options are for compatibility with 1.3 and will be - // removed without notice in a future release. These options - // are not to be documented. - } else if (match_option(option, "-XX:MaxTLERatio=", &tail)) { - // No longer used. - } else if (match_option(option, "-XX:+ResizeTLE", &tail)) { - FLAG_SET_CMDLINE(bool, ResizeTLAB, true); - } else if (match_option(option, "-XX:-ResizeTLE", &tail)) { - FLAG_SET_CMDLINE(bool, ResizeTLAB, false); - } else if (match_option(option, "-XX:+PrintTLE", &tail)) { - FLAG_SET_CMDLINE(bool, PrintTLAB, true); - } else if (match_option(option, "-XX:-PrintTLE", &tail)) { - FLAG_SET_CMDLINE(bool, PrintTLAB, false); - } else if (match_option(option, "-XX:TLEFragmentationRatio=", &tail)) { - // No longer used. - } else if (match_option(option, "-XX:TLESize=", &tail)) { - julong long_tlab_size = 0; - ArgsRange errcode = parse_memory_size(tail, &long_tlab_size, 1); - if (errcode != arg_in_range) { - jio_fprintf(defaultStream::error_stream(), - "Invalid TLAB size: %s\n", option->optionString); - describe_range_error(errcode); - return JNI_EINVAL; - } - FLAG_SET_CMDLINE(uintx, TLABSize, long_tlab_size); - } else if (match_option(option, "-XX:TLEThreadRatio=", &tail)) { - // No longer used. - } else if (match_option(option, "-XX:+UseTLE", &tail)) { - FLAG_SET_CMDLINE(bool, UseTLAB, true); - } else if (match_option(option, "-XX:-UseTLE", &tail)) { - FLAG_SET_CMDLINE(bool, UseTLAB, false); - } else if (match_option(option, "-XX:+DisplayVMOutputToStderr", &tail)) { + } else if (match_option(option, "-XX:+DisplayVMOutputToStderr")) { FLAG_SET_CMDLINE(bool, DisplayVMOutputToStdout, false); FLAG_SET_CMDLINE(bool, DisplayVMOutputToStderr, true); - } else if (match_option(option, "-XX:+DisplayVMOutputToStdout", &tail)) { + } else if (match_option(option, "-XX:+DisplayVMOutputToStdout")) { FLAG_SET_CMDLINE(bool, DisplayVMOutputToStderr, false); FLAG_SET_CMDLINE(bool, DisplayVMOutputToStdout, true); - } else if (match_option(option, "-XX:+ExtendedDTraceProbes", &tail)) { + } else if (match_option(option, "-XX:+ExtendedDTraceProbes")) { #if defined(DTRACE_ENABLED) FLAG_SET_CMDLINE(bool, ExtendedDTraceProbes, true); FLAG_SET_CMDLINE(bool, DTraceMethodProbes, true); @@ -3275,49 +3226,11 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args, return JNI_EINVAL; #endif // defined(DTRACE_ENABLED) #ifdef ASSERT - } else if (match_option(option, "-XX:+FullGCALot", &tail)) { + } else if (match_option(option, "-XX:+FullGCALot")) { FLAG_SET_CMDLINE(bool, FullGCALot, true); // disable scavenge before parallel mark-compact FLAG_SET_CMDLINE(bool, ScavengeBeforeFullGC, false); #endif - } else if (match_option(option, "-XX:CMSParPromoteBlocksToClaim=", &tail)) { - julong cms_blocks_to_claim = (julong)atol(tail); - FLAG_SET_CMDLINE(uintx, CMSParPromoteBlocksToClaim, cms_blocks_to_claim); - jio_fprintf(defaultStream::error_stream(), - "Please use -XX:OldPLABSize in place of " - "-XX:CMSParPromoteBlocksToClaim in the future\n"); - } else if (match_option(option, "-XX:ParCMSPromoteBlocksToClaim=", &tail)) { - julong cms_blocks_to_claim = (julong)atol(tail); - FLAG_SET_CMDLINE(uintx, CMSParPromoteBlocksToClaim, cms_blocks_to_claim); - jio_fprintf(defaultStream::error_stream(), - "Please use -XX:OldPLABSize in place of " - "-XX:ParCMSPromoteBlocksToClaim in the future\n"); - } else if (match_option(option, "-XX:ParallelGCOldGenAllocBufferSize=", &tail)) { - julong old_plab_size = 0; - ArgsRange errcode = parse_memory_size(tail, &old_plab_size, 1); - if (errcode != arg_in_range) { - jio_fprintf(defaultStream::error_stream(), - "Invalid old PLAB size: %s\n", option->optionString); - describe_range_error(errcode); - return JNI_EINVAL; - } - FLAG_SET_CMDLINE(uintx, OldPLABSize, old_plab_size); - jio_fprintf(defaultStream::error_stream(), - "Please use -XX:OldPLABSize in place of " - "-XX:ParallelGCOldGenAllocBufferSize in the future\n"); - } else if (match_option(option, "-XX:ParallelGCToSpaceAllocBufferSize=", &tail)) { - julong young_plab_size = 0; - ArgsRange errcode = parse_memory_size(tail, &young_plab_size, 1); - if (errcode != arg_in_range) { - jio_fprintf(defaultStream::error_stream(), - "Invalid young PLAB size: %s\n", option->optionString); - describe_range_error(errcode); - return JNI_EINVAL; - } - FLAG_SET_CMDLINE(uintx, YoungPLABSize, young_plab_size); - jio_fprintf(defaultStream::error_stream(), - "Please use -XX:YoungPLABSize in place of " - "-XX:ParallelGCToSpaceAllocBufferSize in the future\n"); } else if (match_option(option, "-XX:CMSMarkStackSize=", &tail) || match_option(option, "-XX:G1MarkStackSize=", &tail)) { julong stack_size = 0; @@ -3328,6 +3241,9 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args, describe_range_error(errcode); return JNI_EINVAL; } + jio_fprintf(defaultStream::error_stream(), + "Please use -XX:MarkStackSize in place of " + "-XX:CMSMarkStackSize or -XX:G1MarkStackSize in the future\n"); FLAG_SET_CMDLINE(uintx, MarkStackSize, stack_size); } else if (match_option(option, "-XX:CMSMarkStackSizeMax=", &tail)) { julong max_stack_size = 0; @@ -3339,6 +3255,9 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args, describe_range_error(errcode); return JNI_EINVAL; } + jio_fprintf(defaultStream::error_stream(), + "Please use -XX:MarkStackSizeMax in place of " + "-XX:CMSMarkStackSizeMax in the future\n"); FLAG_SET_CMDLINE(uintx, MarkStackSizeMax, max_stack_size); } else if (match_option(option, "-XX:ParallelMarkingThreads=", &tail) || match_option(option, "-XX:ParallelCMSThreads=", &tail)) { @@ -3348,6 +3267,9 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args, "Invalid concurrent threads: %s\n", option->optionString); return JNI_EINVAL; } + jio_fprintf(defaultStream::error_stream(), + "Please use -XX:ConcGCThreads in place of " + "-XX:ParallelMarkingThreads or -XX:ParallelCMSThreads in the future\n"); FLAG_SET_CMDLINE(uintx, ConcGCThreads, conc_threads); } else if (match_option(option, "-XX:MaxDirectMemorySize=", &tail)) { julong max_direct_memory_size = 0; @@ -3361,7 +3283,7 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args, } FLAG_SET_CMDLINE(uintx, MaxDirectMemorySize, max_direct_memory_size); #if !INCLUDE_MANAGEMENT - } else if (match_option(option, "-XX:+ManagementServer", &tail)) { + } else if (match_option(option, "-XX:+ManagementServer")) { jio_fprintf(defaultStream::error_stream(), "ManagementServer is not supported in this VM.\n"); return JNI_ERR; @@ -3796,23 +3718,23 @@ jint Arguments::parse(const JavaVMInitArgs* args) { settings_file_specified = true; continue; } - if (match_option(option, "-XX:+PrintVMOptions", &tail)) { + if (match_option(option, "-XX:+PrintVMOptions")) { PrintVMOptions = true; continue; } - if (match_option(option, "-XX:-PrintVMOptions", &tail)) { + if (match_option(option, "-XX:-PrintVMOptions")) { PrintVMOptions = false; continue; } - if (match_option(option, "-XX:+IgnoreUnrecognizedVMOptions", &tail)) { + if (match_option(option, "-XX:+IgnoreUnrecognizedVMOptions")) { IgnoreUnrecognizedVMOptions = true; continue; } - if (match_option(option, "-XX:-IgnoreUnrecognizedVMOptions", &tail)) { + if (match_option(option, "-XX:-IgnoreUnrecognizedVMOptions")) { IgnoreUnrecognizedVMOptions = false; continue; } - if (match_option(option, "-XX:+PrintFlagsInitial", &tail)) { + if (match_option(option, "-XX:+PrintFlagsInitial")) { CommandLineFlags::printFlags(tty, false); vm_exit(0); } @@ -3838,7 +3760,7 @@ jint Arguments::parse(const JavaVMInitArgs* args) { #ifndef PRODUCT - if (match_option(option, "-XX:+PrintFlagsWithComments", &tail)) { + if (match_option(option, "-XX:+PrintFlagsWithComments")) { CommandLineFlags::printFlags(tty, true); vm_exit(0); } diff --git a/hotspot/src/share/vm/runtime/deoptimization.cpp b/hotspot/src/share/vm/runtime/deoptimization.cpp index 75da1fef019..90156bfd4ca 100644 --- a/hotspot/src/share/vm/runtime/deoptimization.cpp +++ b/hotspot/src/share/vm/runtime/deoptimization.cpp @@ -176,6 +176,8 @@ Deoptimization::UnrollBlock* Deoptimization::fetch_unroll_info_helper(JavaThread assert(vf->is_compiled_frame(), "Wrong frame type"); chunk->push(compiledVFrame::cast(vf)); + bool realloc_failures = false; + #ifdef COMPILER2 // Reallocate the non-escaping objects and restore their fields. Then // relock objects if synchronization on them was eliminated. @@ -206,19 +208,16 @@ Deoptimization::UnrollBlock* Deoptimization::fetch_unroll_info_helper(JavaThread tty->print_cr("SAVED OOP RESULT " INTPTR_FORMAT " in thread " INTPTR_FORMAT, (void *)result, thread); } } - bool reallocated = false; if (objects != NULL) { JRT_BLOCK - reallocated = realloc_objects(thread, &deoptee, objects, THREAD); + realloc_failures = realloc_objects(thread, &deoptee, objects, THREAD); JRT_END - } - if (reallocated) { - reassign_fields(&deoptee, &map, objects); + reassign_fields(&deoptee, &map, objects, realloc_failures); #ifndef PRODUCT if (TraceDeoptimization) { ttyLocker ttyl; tty->print_cr("REALLOC OBJECTS in thread " INTPTR_FORMAT, thread); - print_objects(objects); + print_objects(objects, realloc_failures); } #endif } @@ -236,7 +235,7 @@ Deoptimization::UnrollBlock* Deoptimization::fetch_unroll_info_helper(JavaThread assert (cvf->scope() != NULL,"expect only compiled java frames"); GrowableArray* monitors = cvf->monitors(); if (monitors->is_nonempty()) { - relock_objects(monitors, thread); + relock_objects(monitors, thread, realloc_failures); #ifndef PRODUCT if (TraceDeoptimization) { ttyLocker ttyl; @@ -247,7 +246,12 @@ Deoptimization::UnrollBlock* Deoptimization::fetch_unroll_info_helper(JavaThread first = false; tty->print_cr("RELOCK OBJECTS in thread " INTPTR_FORMAT, thread); } - tty->print_cr(" object <" INTPTR_FORMAT "> locked", (void *)mi->owner()); + if (mi->owner_is_scalar_replaced()) { + Klass* k = java_lang_Class::as_Klass(mi->owner_klass()); + tty->print_cr(" failed reallocation for klass %s", k->external_name()); + } else { + tty->print_cr(" object <" INTPTR_FORMAT "> locked", (void *)mi->owner()); + } } } } @@ -262,9 +266,14 @@ Deoptimization::UnrollBlock* Deoptimization::fetch_unroll_info_helper(JavaThread // out the java state residing in the vframeArray will be missed. No_Safepoint_Verifier no_safepoint; - vframeArray* array = create_vframeArray(thread, deoptee, &map, chunk); + vframeArray* array = create_vframeArray(thread, deoptee, &map, chunk, realloc_failures); +#ifdef COMPILER2 + if (realloc_failures) { + pop_frames_failed_reallocs(thread, array); + } +#endif - assert(thread->vframe_array_head() == NULL, "Pending deopt!");; + assert(thread->vframe_array_head() == NULL, "Pending deopt!"); thread->set_vframe_array_head(array); // Now that the vframeArray has been created if we have any deferred local writes @@ -718,6 +727,8 @@ bool Deoptimization::realloc_objects(JavaThread* thread, frame* fr, GrowableArra int exception_line = thread->exception_line(); thread->clear_pending_exception(); + bool failures = false; + for (int i = 0; i < objects->length(); i++) { assert(objects->at(i)->is_object(), "invalid debug information"); ObjectValue* sv = (ObjectValue*) objects->at(i); @@ -727,27 +738,34 @@ bool Deoptimization::realloc_objects(JavaThread* thread, frame* fr, GrowableArra if (k->oop_is_instance()) { InstanceKlass* ik = InstanceKlass::cast(k()); - obj = ik->allocate_instance(CHECK_(false)); + obj = ik->allocate_instance(THREAD); } else if (k->oop_is_typeArray()) { TypeArrayKlass* ak = TypeArrayKlass::cast(k()); assert(sv->field_size() % type2size[ak->element_type()] == 0, "non-integral array length"); int len = sv->field_size() / type2size[ak->element_type()]; - obj = ak->allocate(len, CHECK_(false)); + obj = ak->allocate(len, THREAD); } else if (k->oop_is_objArray()) { ObjArrayKlass* ak = ObjArrayKlass::cast(k()); - obj = ak->allocate(sv->field_size(), CHECK_(false)); + obj = ak->allocate(sv->field_size(), THREAD); + } + + if (obj == NULL) { + failures = true; } - assert(obj != NULL, "allocation failed"); assert(sv->value().is_null(), "redundant reallocation"); + assert(obj != NULL || HAS_PENDING_EXCEPTION, "allocation should succeed or we should get an exception"); + CLEAR_PENDING_EXCEPTION; sv->set_value(obj); } - if (pending_exception.not_null()) { + if (failures) { + THROW_OOP_(Universe::out_of_memory_error_realloc_objects(), failures); + } else if (pending_exception.not_null()) { thread->set_pending_exception(pending_exception(), exception_file, exception_line); } - return true; + return failures; } // This assumes that the fields are stored in ObjectValue in the same order @@ -885,12 +903,15 @@ void Deoptimization::reassign_object_array_elements(frame* fr, RegisterMap* reg_ // restore fields of all eliminated objects and arrays -void Deoptimization::reassign_fields(frame* fr, RegisterMap* reg_map, GrowableArray* objects) { +void Deoptimization::reassign_fields(frame* fr, RegisterMap* reg_map, GrowableArray* objects, bool realloc_failures) { for (int i = 0; i < objects->length(); i++) { ObjectValue* sv = (ObjectValue*) objects->at(i); KlassHandle k(java_lang_Class::as_Klass(sv->klass()->as_ConstantOopReadValue()->value()())); Handle obj = sv->value(); - assert(obj.not_null(), "reallocation was missed"); + assert(obj.not_null() || realloc_failures, "reallocation was missed"); + if (obj.is_null()) { + continue; + } if (k->oop_is_instance()) { InstanceKlass* ik = InstanceKlass::cast(k()); @@ -907,34 +928,36 @@ void Deoptimization::reassign_fields(frame* fr, RegisterMap* reg_map, GrowableAr // relock objects for which synchronization was eliminated -void Deoptimization::relock_objects(GrowableArray* monitors, JavaThread* thread) { +void Deoptimization::relock_objects(GrowableArray* monitors, JavaThread* thread, bool realloc_failures) { for (int i = 0; i < monitors->length(); i++) { MonitorInfo* mon_info = monitors->at(i); if (mon_info->eliminated()) { - assert(mon_info->owner() != NULL, "reallocation was missed"); - Handle obj = Handle(mon_info->owner()); - markOop mark = obj->mark(); - if (UseBiasedLocking && mark->has_bias_pattern()) { - // New allocated objects may have the mark set to anonymously biased. - // Also the deoptimized method may called methods with synchronization - // where the thread-local object is bias locked to the current thread. - assert(mark->is_biased_anonymously() || - mark->biased_locker() == thread, "should be locked to current thread"); - // Reset mark word to unbiased prototype. - markOop unbiased_prototype = markOopDesc::prototype()->set_age(mark->age()); - obj->set_mark(unbiased_prototype); + assert(!mon_info->owner_is_scalar_replaced() || realloc_failures, "reallocation was missed"); + if (!mon_info->owner_is_scalar_replaced()) { + Handle obj = Handle(mon_info->owner()); + markOop mark = obj->mark(); + if (UseBiasedLocking && mark->has_bias_pattern()) { + // New allocated objects may have the mark set to anonymously biased. + // Also the deoptimized method may called methods with synchronization + // where the thread-local object is bias locked to the current thread. + assert(mark->is_biased_anonymously() || + mark->biased_locker() == thread, "should be locked to current thread"); + // Reset mark word to unbiased prototype. + markOop unbiased_prototype = markOopDesc::prototype()->set_age(mark->age()); + obj->set_mark(unbiased_prototype); + } + BasicLock* lock = mon_info->lock(); + ObjectSynchronizer::slow_enter(obj, lock, thread); + assert(mon_info->owner()->is_locked(), "object must be locked now"); } - BasicLock* lock = mon_info->lock(); - ObjectSynchronizer::slow_enter(obj, lock, thread); } - assert(mon_info->owner()->is_locked(), "object must be locked now"); } } #ifndef PRODUCT // print information about reallocated objects -void Deoptimization::print_objects(GrowableArray* objects) { +void Deoptimization::print_objects(GrowableArray* objects, bool realloc_failures) { fieldDescriptor fd; for (int i = 0; i < objects->length(); i++) { @@ -944,10 +967,15 @@ void Deoptimization::print_objects(GrowableArray* objects) { tty->print(" object <" INTPTR_FORMAT "> of type ", (void *)sv->value()()); k->print_value(); - tty->print(" allocated (%d bytes)", obj->size() * HeapWordSize); + assert(obj.not_null() || realloc_failures, "reallocation was missed"); + if (obj.is_null()) { + tty->print(" allocation failed"); + } else { + tty->print(" allocated (%d bytes)", obj->size() * HeapWordSize); + } tty->cr(); - if (Verbose) { + if (Verbose && !obj.is_null()) { k->oop_print_on(obj(), tty); } } @@ -955,7 +983,7 @@ void Deoptimization::print_objects(GrowableArray* objects) { #endif #endif // COMPILER2 -vframeArray* Deoptimization::create_vframeArray(JavaThread* thread, frame fr, RegisterMap *reg_map, GrowableArray* chunk) { +vframeArray* Deoptimization::create_vframeArray(JavaThread* thread, frame fr, RegisterMap *reg_map, GrowableArray* chunk, bool realloc_failures) { Events::log(thread, "DEOPT PACKING pc=" INTPTR_FORMAT " sp=" INTPTR_FORMAT, fr.pc(), fr.sp()); #ifndef PRODUCT @@ -998,7 +1026,7 @@ vframeArray* Deoptimization::create_vframeArray(JavaThread* thread, frame fr, Re // Since the Java thread being deoptimized will eventually adjust it's own stack, // the vframeArray containing the unpacking information is allocated in the C heap. // For Compiler1, the caller of the deoptimized frame is saved for use by unpack_frames(). - vframeArray* array = vframeArray::allocate(thread, frame_size, chunk, reg_map, sender, caller, fr); + vframeArray* array = vframeArray::allocate(thread, frame_size, chunk, reg_map, sender, caller, fr, realloc_failures); // Compare the vframeArray to the collected vframes assert(array->structural_compare(thread, chunk), "just checking"); @@ -1013,6 +1041,33 @@ vframeArray* Deoptimization::create_vframeArray(JavaThread* thread, frame fr, Re return array; } +#ifdef COMPILER2 +void Deoptimization::pop_frames_failed_reallocs(JavaThread* thread, vframeArray* array) { + // Reallocation of some scalar replaced objects failed. Record + // that we need to pop all the interpreter frames for the + // deoptimized compiled frame. + assert(thread->frames_to_pop_failed_realloc() == 0, "missed frames to pop?"); + thread->set_frames_to_pop_failed_realloc(array->frames()); + // Unlock all monitors here otherwise the interpreter will see a + // mix of locked and unlocked monitors (because of failed + // reallocations of synchronized objects) and be confused. + for (int i = 0; i < array->frames(); i++) { + MonitorChunk* monitors = array->element(i)->monitors(); + if (monitors != NULL) { + for (int j = 0; j < monitors->number_of_monitors(); j++) { + BasicObjectLock* src = monitors->at(j); + if (src->obj() != NULL) { + ObjectSynchronizer::fast_exit(src->obj(), src->lock(), thread); + } + } + array->element(i)->free_monitors(thread); +#ifdef ASSERT + array->element(i)->set_removed_monitors(); +#endif + } + } +} +#endif static void collect_monitors(compiledVFrame* cvf, GrowableArray* objects_to_revoke) { GrowableArray* monitors = cvf->monitors(); diff --git a/hotspot/src/share/vm/runtime/deoptimization.hpp b/hotspot/src/share/vm/runtime/deoptimization.hpp index ee461196bd0..e04ad5a0043 100644 --- a/hotspot/src/share/vm/runtime/deoptimization.hpp +++ b/hotspot/src/share/vm/runtime/deoptimization.hpp @@ -125,13 +125,14 @@ class Deoptimization : AllStatic { static bool realloc_objects(JavaThread* thread, frame* fr, GrowableArray* objects, TRAPS); static void reassign_type_array_elements(frame* fr, RegisterMap* reg_map, ObjectValue* sv, typeArrayOop obj, BasicType type); static void reassign_object_array_elements(frame* fr, RegisterMap* reg_map, ObjectValue* sv, objArrayOop obj); - static void reassign_fields(frame* fr, RegisterMap* reg_map, GrowableArray* objects); - static void relock_objects(GrowableArray* monitors, JavaThread* thread); - NOT_PRODUCT(static void print_objects(GrowableArray* objects);) + static void reassign_fields(frame* fr, RegisterMap* reg_map, GrowableArray* objects, bool realloc_failures); + static void relock_objects(GrowableArray* monitors, JavaThread* thread, bool realloc_failures); + static void pop_frames_failed_reallocs(JavaThread* thread, vframeArray* array); + NOT_PRODUCT(static void print_objects(GrowableArray* objects, bool realloc_failures);) #endif // COMPILER2 public: - static vframeArray* create_vframeArray(JavaThread* thread, frame fr, RegisterMap *reg_map, GrowableArray* chunk); + static vframeArray* create_vframeArray(JavaThread* thread, frame fr, RegisterMap *reg_map, GrowableArray* chunk, bool realloc_failures); // Interface used for unpacking deoptimized frames diff --git a/hotspot/src/share/vm/runtime/globals.hpp b/hotspot/src/share/vm/runtime/globals.hpp index 25bd4c7a215..21c835722eb 100644 --- a/hotspot/src/share/vm/runtime/globals.hpp +++ b/hotspot/src/share/vm/runtime/globals.hpp @@ -1341,7 +1341,7 @@ class CommandLineFlags { develop(bool, TraceClassInitialization, false, \ "Trace class initialization") \ \ - develop(bool, TraceExceptions, false, \ + product(bool, TraceExceptions, false, \ "Trace exceptions") \ \ develop(bool, TraceICs, false, \ @@ -1472,7 +1472,8 @@ class CommandLineFlags { "Size of young gen promotion LAB's (in HeapWords)") \ \ product(uintx, OldPLABSize, 1024, \ - "Size of old gen promotion LAB's (in HeapWords)") \ + "Size of old gen promotion LAB's (in HeapWords), or Number \ + of blocks to attempt to claim when refilling CMS LAB's") \ \ product(uintx, GCTaskTimeStampEntries, 200, \ "Number of time stamp entries per gc worker thread") \ @@ -1583,14 +1584,10 @@ class CommandLineFlags { "The number of cards in each chunk of the parallel chunks used " \ "during card table scanning") \ \ - product(uintx, CMSParPromoteBlocksToClaim, 16, \ - "Number of blocks to attempt to claim when refilling CMS LAB's " \ - "for parallel GC") \ - \ product(uintx, OldPLABWeight, 50, \ "Percentage (0-100) used to weight the current sample when " \ "computing exponentially decaying average for resizing " \ - "CMSParPromoteBlocksToClaim") \ + "OldPLABSize") \ \ product(bool, ResizeOldPLAB, true, \ "Dynamically resize (old gen) promotion LAB's") \ diff --git a/hotspot/src/share/vm/runtime/mutex.cpp b/hotspot/src/share/vm/runtime/mutex.cpp index a414ab815e0..3879e82a4ae 100644 --- a/hotspot/src/share/vm/runtime/mutex.cpp +++ b/hotspot/src/share/vm/runtime/mutex.cpp @@ -895,6 +895,11 @@ int Monitor::IWait(Thread * Self, jlong timo) { // of Mutex-Monitor and instead directly address the underlying design flaw. void Monitor::lock(Thread * Self) { + // Ensure that the Monitor requires/allows safepoint checks. + assert(_safepoint_check_required != Monitor::_safepoint_check_never, + err_msg("This lock should never have a safepoint check: %s", + name())); + #ifdef CHECK_UNHANDLED_OOPS // Clear unhandled oops so we get a crash right away. Only clear for non-vm // or GC threads. @@ -953,6 +958,10 @@ void Monitor::lock() { // thread state set to be in VM, the safepoint synchronization code will deadlock! void Monitor::lock_without_safepoint_check(Thread * Self) { + // Ensure that the Monitor does not require or allow safepoint checks. + assert(_safepoint_check_required != Monitor::_safepoint_check_always, + err_msg("This lock should always have a safepoint check: %s", + name())); assert(_owner != Self, "invariant"); ILock(Self); assert(_owner == NULL, "invariant"); @@ -1082,6 +1091,12 @@ void Monitor::jvm_raw_unlock() { bool Monitor::wait(bool no_safepoint_check, long timeout, bool as_suspend_equivalent) { + // Make sure safepoint checking is used properly. + assert(!(_safepoint_check_required == Monitor::_safepoint_check_never && no_safepoint_check == false), + err_msg("This lock should never have a safepoint check: %s", name())); + assert(!(_safepoint_check_required == Monitor::_safepoint_check_always && no_safepoint_check == true), + err_msg("This lock should always have a safepoint check: %s", name())); + Thread * const Self = Thread::current(); assert(_owner == Self, "invariant"); assert(ILocked(), "invariant"); @@ -1168,11 +1183,13 @@ void Monitor::ClearMonitor(Monitor * m, const char *name) { Monitor::Monitor() { ClearMonitor(this); } -Monitor::Monitor(int Rank, const char * name, bool allow_vm_block) { +Monitor::Monitor(int Rank, const char * name, bool allow_vm_block, + SafepointCheckRequired safepoint_check_required) { ClearMonitor(this, name); #ifdef ASSERT _allow_vm_block = allow_vm_block; _rank = Rank; + NOT_PRODUCT(_safepoint_check_required = safepoint_check_required;) #endif } @@ -1180,11 +1197,13 @@ Mutex::~Mutex() { assert((UNS(_owner)|UNS(_LockWord.FullWord)|UNS(_EntryList)|UNS(_WaitSet)|UNS(_OnDeck)) == 0, ""); } -Mutex::Mutex(int Rank, const char * name, bool allow_vm_block) { +Mutex::Mutex(int Rank, const char * name, bool allow_vm_block, + SafepointCheckRequired safepoint_check_required) { ClearMonitor((Monitor *) this, name); #ifdef ASSERT _allow_vm_block = allow_vm_block; _rank = Rank; + NOT_PRODUCT(_safepoint_check_required = safepoint_check_required;) #endif } diff --git a/hotspot/src/share/vm/runtime/mutex.hpp b/hotspot/src/share/vm/runtime/mutex.hpp index dbd32669549..a510cdb6e6f 100644 --- a/hotspot/src/share/vm/runtime/mutex.hpp +++ b/hotspot/src/share/vm/runtime/mutex.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 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 @@ -154,6 +154,24 @@ class Monitor : public CHeapObj { _as_suspend_equivalent_flag = true }; + // Locks can be acquired with or without safepoint check. + // Monitor::lock and Monitor::lock_without_safepoint_check + // checks these flags when acquiring a lock to ensure + // consistent checking for each lock. + // A few existing locks will sometimes have a safepoint check and + // sometimes not, but these locks are set up in such a way to avoid deadlocks. + enum SafepointCheckRequired { + _safepoint_check_never, // Monitors with this value will cause errors + // when acquired with a safepoint check. + _safepoint_check_sometimes, // Certain locks are called sometimes with and + // sometimes without safepoint checks. These + // locks will not produce errors when locked. + _safepoint_check_always // Causes error if locked without a safepoint + // check. + }; + + NOT_PRODUCT(SafepointCheckRequired _safepoint_check_required;) + enum WaitResults { CONDVAR_EVENT, // Wait returned because of condition variable notification INTERRUPT_EVENT, // Wait returned because waiting thread was interrupted @@ -175,7 +193,8 @@ class Monitor : public CHeapObj { Monitor() ; public: - Monitor(int rank, const char *name, bool allow_vm_block=false); + Monitor(int rank, const char *name, bool allow_vm_block = false, + SafepointCheckRequired safepoint_check_required = _safepoint_check_always); ~Monitor(); // Wait until monitor is notified (or times out). @@ -261,7 +280,8 @@ class Monitor : public CHeapObj { class Mutex : public Monitor { // degenerate Monitor public: - Mutex (int rank, const char *name, bool allow_vm_block=false); + Mutex(int rank, const char *name, bool allow_vm_block = false, + SafepointCheckRequired safepoint_check_required = _safepoint_check_always); ~Mutex () ; private: bool notify () { ShouldNotReachHere(); return false; } diff --git a/hotspot/src/share/vm/runtime/mutexLocker.cpp b/hotspot/src/share/vm/runtime/mutexLocker.cpp index a2c53bb885e..11badd0c17b 100644 --- a/hotspot/src/share/vm/runtime/mutexLocker.cpp +++ b/hotspot/src/share/vm/runtime/mutexLocker.cpp @@ -167,131 +167,133 @@ void assert_lock_strong(const Monitor * lock) { } #endif -#define def(var, type, pri, vm_block) { \ - var = new type(Mutex::pri, #var, vm_block); \ - assert(_num_mutex < MAX_NUM_MUTEX, \ - "increase MAX_NUM_MUTEX"); \ - _mutex_array[_num_mutex++] = var; \ +#define def(var, type, pri, vm_block, safepoint_check_allowed ) { \ + var = new type(Mutex::pri, #var, vm_block, safepoint_check_allowed); \ + assert(_num_mutex < MAX_NUM_MUTEX, "increase MAX_NUM_MUTEX"); \ + _mutex_array[_num_mutex] = var; \ } void mutex_init() { - def(tty_lock , Mutex , event, true ); // allow to lock in VM + def(tty_lock , Mutex , event, true, Monitor::_safepoint_check_never); // allow to lock in VM + + def(CGC_lock , Monitor, special, true, Monitor::_safepoint_check_never); // coordinate between fore- and background GC + def(STS_lock , Monitor, leaf, true, Monitor::_safepoint_check_never); - def(CGC_lock , Monitor, special, true ); // coordinate between fore- and background GC - def(STS_lock , Monitor, leaf, true ); if (UseConcMarkSweepGC || UseG1GC) { - def(FullGCCount_lock , Monitor, leaf, true ); // in support of ExplicitGCInvokesConcurrent + def(FullGCCount_lock , Monitor, leaf, true, Monitor::_safepoint_check_never); // in support of ExplicitGCInvokesConcurrent } if (UseG1GC) { - def(CMark_lock , Monitor, nonleaf, true ); // coordinate concurrent mark thread - def(CMRegionStack_lock , Mutex, leaf, true ); - def(SATB_Q_FL_lock , Mutex , special, true ); - def(SATB_Q_CBL_mon , Monitor, nonleaf, true ); - def(Shared_SATB_Q_lock , Mutex, nonleaf, true ); - def(DirtyCardQ_FL_lock , Mutex , special, true ); - def(DirtyCardQ_CBL_mon , Monitor, nonleaf, true ); - def(Shared_DirtyCardQ_lock , Mutex, nonleaf, true ); + def(CMark_lock , Monitor, nonleaf, true, Monitor::_safepoint_check_never); // coordinate concurrent mark thread + def(CMRegionStack_lock , Mutex, leaf, true, Monitor::_safepoint_check_never); + def(SATB_Q_FL_lock , Mutex , special, true, Monitor::_safepoint_check_never); + def(SATB_Q_CBL_mon , Monitor, nonleaf, true, Monitor::_safepoint_check_never); + def(Shared_SATB_Q_lock , Mutex, nonleaf, true, Monitor::_safepoint_check_never); - def(FreeList_lock , Mutex, leaf , true ); - def(SecondaryFreeList_lock , Monitor, leaf , true ); - def(OldSets_lock , Mutex , leaf , true ); - def(RootRegionScan_lock , Monitor, leaf , true ); - def(MMUTracker_lock , Mutex , leaf , true ); - def(HotCardCache_lock , Mutex , special , true ); - def(EvacFailureStack_lock , Mutex , nonleaf , true ); + def(DirtyCardQ_FL_lock , Mutex , special, true, Monitor::_safepoint_check_never); + def(DirtyCardQ_CBL_mon , Monitor, nonleaf, true, Monitor::_safepoint_check_never); + def(Shared_DirtyCardQ_lock , Mutex, nonleaf, true, Monitor::_safepoint_check_never); - def(StringDedupQueue_lock , Monitor, leaf, true ); - def(StringDedupTable_lock , Mutex , leaf, true ); + def(FreeList_lock , Mutex, leaf , true, Monitor::_safepoint_check_never); + def(SecondaryFreeList_lock , Monitor, leaf , true, Monitor::_safepoint_check_never); + def(OldSets_lock , Mutex , leaf , true, Monitor::_safepoint_check_never); + def(RootRegionScan_lock , Monitor, leaf , true, Monitor::_safepoint_check_never); + def(MMUTracker_lock , Mutex , leaf , true, Monitor::_safepoint_check_never); + def(HotCardCache_lock , Mutex , special , true, Monitor::_safepoint_check_never); + def(EvacFailureStack_lock , Mutex , nonleaf , true, Monitor::_safepoint_check_never); + + def(StringDedupQueue_lock , Monitor, leaf, true, Monitor::_safepoint_check_never); + def(StringDedupTable_lock , Mutex , leaf, true, Monitor::_safepoint_check_never); } - def(ParGCRareEvent_lock , Mutex , leaf , true ); - def(DerivedPointerTableGC_lock , Mutex, leaf, true ); - def(CodeCache_lock , Monitor, special, true ); - def(Interrupt_lock , Monitor, special, true ); // used for interrupt processing - def(RawMonitor_lock , Mutex, special, true ); - def(OopMapCacheAlloc_lock , Mutex, leaf, true ); // used for oop_map_cache allocation. + def(ParGCRareEvent_lock , Mutex , leaf , true, Monitor::_safepoint_check_sometimes); + def(DerivedPointerTableGC_lock , Mutex, leaf, true, Monitor::_safepoint_check_never); + def(CodeCache_lock , Mutex , special, true, Monitor::_safepoint_check_never); + def(Interrupt_lock , Monitor, special, true, Monitor::_safepoint_check_never); // used for interrupt processing + def(RawMonitor_lock , Mutex, special, true, Monitor::_safepoint_check_never); + def(OopMapCacheAlloc_lock , Mutex, leaf, true, Monitor::_safepoint_check_always); // used for oop_map_cache allocation. - def(Patching_lock , Mutex , special, true ); // used for safepointing and code patching. - def(ObjAllocPost_lock , Monitor, special, false); - def(Service_lock , Monitor, special, true ); // used for service thread operations - def(JmethodIdCreation_lock , Mutex , leaf, true ); // used for creating jmethodIDs. + def(Patching_lock , Mutex , special, true, Monitor::_safepoint_check_never); // used for safepointing and code patching. + def(ObjAllocPost_lock , Monitor, special, false, Monitor::_safepoint_check_never); + def(Service_lock , Monitor, special, true, Monitor::_safepoint_check_never); // used for service thread operations + def(JmethodIdCreation_lock , Mutex , leaf, true, Monitor::_safepoint_check_always); // used for creating jmethodIDs. - def(SystemDictionary_lock , Monitor, leaf, true ); // lookups done by VM thread - def(PackageTable_lock , Mutex , leaf, false); - def(InlineCacheBuffer_lock , Mutex , leaf, true ); - def(VMStatistic_lock , Mutex , leaf, false); - def(ExpandHeap_lock , Mutex , leaf, true ); // Used during compilation by VM thread - def(JNIHandleBlockFreeList_lock , Mutex , leaf, true ); // handles are used by VM thread - def(SignatureHandlerLibrary_lock , Mutex , leaf, false); - def(SymbolTable_lock , Mutex , leaf+2, true ); - def(StringTable_lock , Mutex , leaf, true ); - def(ProfilePrint_lock , Mutex , leaf, false); // serial profile printing - def(ExceptionCache_lock , Mutex , leaf, false); // serial profile printing - def(OsrList_lock , Mutex , leaf, true ); - def(Debug1_lock , Mutex , leaf, true ); + def(SystemDictionary_lock , Monitor, leaf, true, Monitor::_safepoint_check_always); // lookups done by VM thread + def(PackageTable_lock , Mutex , leaf, false, Monitor::_safepoint_check_always); + def(InlineCacheBuffer_lock , Mutex , leaf, true, Monitor::_safepoint_check_always); + def(VMStatistic_lock , Mutex , leaf, false, Monitor::_safepoint_check_always); + def(ExpandHeap_lock , Mutex , leaf, true, Monitor::_safepoint_check_always); // Used during compilation by VM thread + def(JNIHandleBlockFreeList_lock , Mutex , leaf, true, Monitor::_safepoint_check_never); // handles are used by VM thread + def(SignatureHandlerLibrary_lock , Mutex , leaf, false, Monitor::_safepoint_check_always); + def(SymbolTable_lock , Mutex , leaf+2, true, Monitor::_safepoint_check_always); + def(StringTable_lock , Mutex , leaf, true, Monitor::_safepoint_check_always); + def(ProfilePrint_lock , Mutex , leaf, false, Monitor::_safepoint_check_always); // serial profile printing + def(ExceptionCache_lock , Mutex , leaf, false, Monitor::_safepoint_check_always); // serial profile printing + def(OsrList_lock , Mutex , leaf, true, Monitor::_safepoint_check_never); + def(Debug1_lock , Mutex , leaf, true, Monitor::_safepoint_check_never); #ifndef PRODUCT - def(FullGCALot_lock , Mutex , leaf, false); // a lock to make FullGCALot MT safe + def(FullGCALot_lock , Mutex , leaf, false, Monitor::_safepoint_check_always); // a lock to make FullGCALot MT safe #endif - def(BeforeExit_lock , Monitor, leaf, true ); - def(PerfDataMemAlloc_lock , Mutex , leaf, true ); // used for allocating PerfData memory for performance data - def(PerfDataManager_lock , Mutex , leaf, true ); // used for synchronized access to PerfDataManager resources + def(BeforeExit_lock , Monitor, leaf, true, Monitor::_safepoint_check_always); + def(PerfDataMemAlloc_lock , Mutex , leaf, true, Monitor::_safepoint_check_always); // used for allocating PerfData memory for performance data + def(PerfDataManager_lock , Mutex , leaf, true, Monitor::_safepoint_check_always); // used for synchronized access to PerfDataManager resources // CMS_modUnionTable_lock leaf - // CMS_bitMap_lock leaf + 1 - // CMS_freeList_lock leaf + 2 + // CMS_bitMap_lock leaf 1 + // CMS_freeList_lock leaf 2 - def(Safepoint_lock , Monitor, safepoint, true ); // locks SnippetCache_lock/Threads_lock + def(Safepoint_lock , Monitor, safepoint, true, Monitor::_safepoint_check_sometimes); // locks SnippetCache_lock/Threads_lock - def(Threads_lock , Monitor, barrier, true ); + def(Threads_lock , Monitor, barrier, true, Monitor::_safepoint_check_sometimes); - def(VMOperationQueue_lock , Monitor, nonleaf, true ); // VM_thread allowed to block on these - def(VMOperationRequest_lock , Monitor, nonleaf, true ); - def(RetData_lock , Mutex , nonleaf, false); - def(Terminator_lock , Monitor, nonleaf, true ); - def(VtableStubs_lock , Mutex , nonleaf, true ); - def(Notify_lock , Monitor, nonleaf, true ); - def(JNIGlobalHandle_lock , Mutex , nonleaf, true ); // locks JNIHandleBlockFreeList_lock - def(JNICritical_lock , Monitor, nonleaf, true ); // used for JNI critical regions - def(AdapterHandlerLibrary_lock , Mutex , nonleaf, true); + def(VMOperationQueue_lock , Monitor, nonleaf, true, Monitor::_safepoint_check_sometimes); // VM_thread allowed to block on these + def(VMOperationRequest_lock , Monitor, nonleaf, true, Monitor::_safepoint_check_sometimes); + def(RetData_lock , Mutex , nonleaf, false, Monitor::_safepoint_check_always); + def(Terminator_lock , Monitor, nonleaf, true, Monitor::_safepoint_check_sometimes); + def(VtableStubs_lock , Mutex , nonleaf, true, Monitor::_safepoint_check_always); + def(Notify_lock , Monitor, nonleaf, true, Monitor::_safepoint_check_always); + def(JNIGlobalHandle_lock , Mutex , nonleaf, true, Monitor::_safepoint_check_always); // locks JNIHandleBlockFreeList_lock + def(JNICritical_lock , Monitor, nonleaf, true, Monitor::_safepoint_check_always); // used for JNI critical regions + def(AdapterHandlerLibrary_lock , Mutex , nonleaf, true, Monitor::_safepoint_check_always); if (UseConcMarkSweepGC) { - def(SLT_lock , Monitor, nonleaf, false ); - // used in CMS GC for locking PLL lock + def(SLT_lock , Monitor, nonleaf, false, Monitor::_safepoint_check_never); // used in CMS GC for locking PLL lock } - def(Heap_lock , Monitor, nonleaf+1, false); - def(JfieldIdCreation_lock , Mutex , nonleaf+1, true ); // jfieldID, Used in VM_Operation - def(MemberNameTable_lock , Mutex , nonleaf+1, false); // Used to protect MemberNameTable - def(CompiledIC_lock , Mutex , nonleaf+2, false); // locks VtableStubs_lock, InlineCacheBuffer_lock - def(CompileTaskAlloc_lock , Mutex , nonleaf+2, true ); - def(CompileStatistics_lock , Mutex , nonleaf+2, false); - def(MultiArray_lock , Mutex , nonleaf+2, false); // locks SymbolTable_lock + def(Heap_lock , Monitor, nonleaf+1, false, Monitor::_safepoint_check_sometimes); + def(JfieldIdCreation_lock , Mutex , nonleaf+1, true, Monitor::_safepoint_check_always); // jfieldID, Used in VM_Operation + def(MemberNameTable_lock , Mutex , nonleaf+1, false, Monitor::_safepoint_check_always); // Used to protect MemberNameTable - def(JvmtiThreadState_lock , Mutex , nonleaf+2, false); // Used by JvmtiThreadState/JvmtiEventController - def(JvmtiPendingEvent_lock , Monitor, nonleaf, false); // Used by JvmtiCodeBlobEvents - def(Management_lock , Mutex , nonleaf+2, false); // used for JVM management + def(CompiledIC_lock , Mutex , nonleaf+2, false, Monitor::_safepoint_check_always); // locks VtableStubs_lock, InlineCacheBuffer_lock + def(CompileTaskAlloc_lock , Mutex , nonleaf+2, true, Monitor::_safepoint_check_always); + def(CompileStatistics_lock , Mutex , nonleaf+2, false, Monitor::_safepoint_check_always); + def(MultiArray_lock , Mutex , nonleaf+2, false, Monitor::_safepoint_check_always); // locks SymbolTable_lock - def(Compile_lock , Mutex , nonleaf+3, true ); - def(MethodData_lock , Mutex , nonleaf+3, false); + def(JvmtiThreadState_lock , Mutex , nonleaf+2, false, Monitor::_safepoint_check_always); // Used by JvmtiThreadState/JvmtiEventController + def(JvmtiPendingEvent_lock , Monitor, nonleaf, false, Monitor::_safepoint_check_never); // Used by JvmtiCodeBlobEvents + def(Management_lock , Mutex , nonleaf+2, false, Monitor::_safepoint_check_always); // used for JVM management - def(MethodCompileQueue_lock , Monitor, nonleaf+4, true ); - def(Debug2_lock , Mutex , nonleaf+4, true ); - def(Debug3_lock , Mutex , nonleaf+4, true ); - def(ProfileVM_lock , Monitor, special, false); // used for profiling of the VMThread - def(CompileThread_lock , Monitor, nonleaf+5, false ); - def(PeriodicTask_lock , Monitor, nonleaf+5, true); + def(Compile_lock , Mutex , nonleaf+3, true, Monitor::_safepoint_check_sometimes); + def(MethodData_lock , Mutex , nonleaf+3, false, Monitor::_safepoint_check_always); + + def(MethodCompileQueue_lock , Monitor, nonleaf+4, true, Monitor::_safepoint_check_always); + def(Debug2_lock , Mutex , nonleaf+4, true, Monitor::_safepoint_check_never); + def(Debug3_lock , Mutex , nonleaf+4, true, Monitor::_safepoint_check_never); + def(ProfileVM_lock , Monitor, special, false, Monitor::_safepoint_check_never); // used for profiling of the VMThread + def(CompileThread_lock , Monitor, nonleaf+5, false, Monitor::_safepoint_check_always); + def(PeriodicTask_lock , Monitor, nonleaf+5, true, Monitor::_safepoint_check_sometimes); if (WhiteBoxAPI) { - def(Compilation_lock , Monitor, leaf, false ); + def(Compilation_lock , Monitor, leaf, false, Monitor::_safepoint_check_never); } + #ifdef INCLUDE_TRACE - def(JfrMsg_lock , Monitor, leaf, true); - def(JfrBuffer_lock , Mutex, leaf, true); - def(JfrThreadGroups_lock , Mutex, leaf, true); - def(JfrStream_lock , Mutex, nonleaf, true); - def(JfrStacktrace_lock , Mutex, special, true); + def(JfrMsg_lock , Monitor, leaf, true, Monitor::_safepoint_check_always); + def(JfrBuffer_lock , Mutex, leaf, true, Monitor::_safepoint_check_never); + def(JfrThreadGroups_lock , Mutex, leaf, true, Monitor::_safepoint_check_always); + def(JfrStream_lock , Mutex, nonleaf, true, Monitor::_safepoint_check_never); + def(JfrStacktrace_lock , Mutex, special, true, Monitor::_safepoint_check_sometimes); #endif #ifndef SUPPORTS_NATIVE_CX8 - def(UnsafeJlong_lock , Mutex, special, false); + def(UnsafeJlong_lock , Mutex, special, false, Monitor::_safepoint_check_never); #endif } diff --git a/hotspot/src/share/vm/runtime/os.cpp b/hotspot/src/share/vm/runtime/os.cpp index b97651a2949..665688b6808 100644 --- a/hotspot/src/share/vm/runtime/os.cpp +++ b/hotspot/src/share/vm/runtime/os.cpp @@ -1588,6 +1588,11 @@ bool os::release_memory(char* addr, size_t bytes) { return res; } +void os::pretouch_memory(char* start, char* end) { + for (volatile char *p = start; p < end; p += os::vm_page_size()) { + *p = 0; + } +} char* os::map_memory(int fd, const char* file_name, size_t file_offset, char *addr, size_t bytes, bool read_only, diff --git a/hotspot/src/share/vm/runtime/os.hpp b/hotspot/src/share/vm/runtime/os.hpp index d3650d5431d..ecd2e24a0fa 100644 --- a/hotspot/src/share/vm/runtime/os.hpp +++ b/hotspot/src/share/vm/runtime/os.hpp @@ -311,6 +311,12 @@ class os: AllStatic { static bool uncommit_memory(char* addr, size_t bytes); static bool release_memory(char* addr, size_t bytes); + // Touch memory pages that cover the memory range from start to end (exclusive) + // to make the OS back the memory range with actual memory. + // Current implementation may not touch the last page if unaligned addresses + // are passed. + static void pretouch_memory(char* start, char* end); + enum ProtType { MEM_PROT_NONE, MEM_PROT_READ, MEM_PROT_RW, MEM_PROT_RWX }; static bool protect_memory(char* addr, size_t bytes, ProtType prot, bool is_committed = true); diff --git a/hotspot/src/share/vm/runtime/sharedRuntime.cpp b/hotspot/src/share/vm/runtime/sharedRuntime.cpp index 409a867afaf..fa1f5672292 100644 --- a/hotspot/src/share/vm/runtime/sharedRuntime.cpp +++ b/hotspot/src/share/vm/runtime/sharedRuntime.cpp @@ -456,6 +456,7 @@ JRT_END address SharedRuntime::raw_exception_handler_for_return_address(JavaThread* thread, address return_address) { assert(frame::verify_return_pc(return_address), err_msg("must be a return address: " INTPTR_FORMAT, return_address)); + assert(thread->frames_to_pop_failed_realloc() == 0 || Interpreter::contains(return_address), "missed frames to pop?"); // Reset method handle flag. thread->set_is_method_handle_return(false); diff --git a/hotspot/src/share/vm/runtime/sweeper.cpp b/hotspot/src/share/vm/runtime/sweeper.cpp index 72d7868f727..d2a9ff91f96 100644 --- a/hotspot/src/share/vm/runtime/sweeper.cpp +++ b/hotspot/src/share/vm/runtime/sweeper.cpp @@ -158,7 +158,7 @@ Tickspan NMethodSweeper::_total_time_this_sweep; // Total time thi Tickspan NMethodSweeper::_peak_sweep_time; // Peak time for a full sweep Tickspan NMethodSweeper::_peak_sweep_fraction_time; // Peak time sweeping one fraction -Monitor* NMethodSweeper::_stat_lock = new Monitor(Mutex::special, "Sweeper::Statistics", true); +Monitor* NMethodSweeper::_stat_lock = new Monitor(Mutex::special, "Sweeper::Statistics", true, Monitor::_safepoint_check_sometimes); class MarkActivationClosure: public CodeBlobClosure { public: diff --git a/hotspot/src/share/vm/runtime/thread.cpp b/hotspot/src/share/vm/runtime/thread.cpp index 6ce71c36001..9a7df7a4928 100644 --- a/hotspot/src/share/vm/runtime/thread.cpp +++ b/hotspot/src/share/vm/runtime/thread.cpp @@ -230,7 +230,8 @@ Thread::Thread() { _visited_for_critical_count = false; #endif - _SR_lock = new Monitor(Mutex::suspend_resume, "SR_lock", true); + _SR_lock = new Monitor(Mutex::suspend_resume, "SR_lock", true, + Monitor::_safepoint_check_sometimes); _suspend_flags = 0; // thread-specific hashCode stream generator state - Marsaglia shift-xor form @@ -1448,6 +1449,7 @@ void JavaThread::initialize() { _popframe_condition = popframe_inactive; _popframe_preserved_args = NULL; _popframe_preserved_args_size = 0; + _frames_to_pop_failed_realloc = 0; pd_initialize(); } diff --git a/hotspot/src/share/vm/runtime/thread.hpp b/hotspot/src/share/vm/runtime/thread.hpp index 44e10aae90b..399a2cbe671 100644 --- a/hotspot/src/share/vm/runtime/thread.hpp +++ b/hotspot/src/share/vm/runtime/thread.hpp @@ -908,6 +908,12 @@ class JavaThread: public Thread { // This is set to popframe_pending to signal that top Java frame should be popped immediately int _popframe_condition; + // If reallocation of scalar replaced objects fails, we throw OOM + // and during exception propagation, pop the top + // _frames_to_pop_failed_realloc frames, the ones that reference + // failed reallocations. + int _frames_to_pop_failed_realloc; + #ifndef PRODUCT int _jmp_ring_index; struct { @@ -1567,6 +1573,10 @@ class JavaThread: public Thread { void clr_pop_frame_in_process(void) { _popframe_condition &= ~popframe_processing_bit; } #endif + int frames_to_pop_failed_realloc() const { return _frames_to_pop_failed_realloc; } + void set_frames_to_pop_failed_realloc(int nb) { _frames_to_pop_failed_realloc = nb; } + void dec_frames_to_pop_failed_realloc() { _frames_to_pop_failed_realloc--; } + private: // Saved incoming arguments to popped frame. // Used only when popped interpreted frame returns to deoptimized frame. diff --git a/hotspot/src/share/vm/runtime/vframeArray.cpp b/hotspot/src/share/vm/runtime/vframeArray.cpp index 6a3652c0ea1..d3e989e59e2 100644 --- a/hotspot/src/share/vm/runtime/vframeArray.cpp +++ b/hotspot/src/share/vm/runtime/vframeArray.cpp @@ -57,7 +57,7 @@ void vframeArrayElement::free_monitors(JavaThread* jt) { } } -void vframeArrayElement::fill_in(compiledVFrame* vf) { +void vframeArrayElement::fill_in(compiledVFrame* vf, bool realloc_failures) { // Copy the information from the compiled vframe to the // interpreter frame we will be creating to replace vf @@ -65,6 +65,9 @@ void vframeArrayElement::fill_in(compiledVFrame* vf) { _method = vf->method(); _bci = vf->raw_bci(); _reexecute = vf->should_reexecute(); +#ifdef ASSERT + _removed_monitors = false; +#endif int index; @@ -82,11 +85,15 @@ void vframeArrayElement::fill_in(compiledVFrame* vf) { // Migrate the BasicLocks from the stack to the monitor chunk for (index = 0; index < list->length(); index++) { MonitorInfo* monitor = list->at(index); - assert(!monitor->owner_is_scalar_replaced(), "object should be reallocated already"); - assert(monitor->owner() == NULL || (!monitor->owner()->is_unlocked() && !monitor->owner()->has_bias_pattern()), "object must be null or locked, and unbiased"); + assert(!monitor->owner_is_scalar_replaced() || realloc_failures, "object should be reallocated already"); BasicObjectLock* dest = _monitors->at(index); - dest->set_obj(monitor->owner()); - monitor->lock()->move_to(monitor->owner(), dest->lock()); + if (monitor->owner_is_scalar_replaced()) { + dest->set_obj(NULL); + } else { + assert(monitor->owner() == NULL || (!monitor->owner()->is_unlocked() && !monitor->owner()->has_bias_pattern()), "object must be null or locked, and unbiased"); + dest->set_obj(monitor->owner()); + monitor->lock()->move_to(monitor->owner(), dest->lock()); + } } } @@ -111,7 +118,7 @@ void vframeArrayElement::fill_in(compiledVFrame* vf) { StackValue* value = locs->at(index); switch(value->type()) { case T_OBJECT: - assert(!value->obj_is_scalar_replaced(), "object should be reallocated already"); + assert(!value->obj_is_scalar_replaced() || realloc_failures, "object should be reallocated already"); // preserve object type _locals->add( new StackValue(cast_from_oop((value->get_obj()())), T_OBJECT )); break; @@ -136,7 +143,7 @@ void vframeArrayElement::fill_in(compiledVFrame* vf) { StackValue* value = exprs->at(index); switch(value->type()) { case T_OBJECT: - assert(!value->obj_is_scalar_replaced(), "object should be reallocated already"); + assert(!value->obj_is_scalar_replaced() || realloc_failures, "object should be reallocated already"); // preserve object type _expressions->add( new StackValue(cast_from_oop((value->get_obj()())), T_OBJECT )); break; @@ -287,7 +294,7 @@ void vframeArrayElement::unpack_on_stack(int caller_actual_parameters, _frame.patch_pc(thread, pc); - assert (!method()->is_synchronized() || locks > 0, "synchronized methods must have monitors"); + assert (!method()->is_synchronized() || locks > 0 || _removed_monitors, "synchronized methods must have monitors"); BasicObjectLock* top = iframe()->interpreter_frame_monitor_begin(); for (int index = 0; index < locks; index++) { @@ -439,7 +446,8 @@ int vframeArrayElement::on_stack_size(int callee_parameters, vframeArray* vframeArray::allocate(JavaThread* thread, int frame_size, GrowableArray* chunk, - RegisterMap *reg_map, frame sender, frame caller, frame self) { + RegisterMap *reg_map, frame sender, frame caller, frame self, + bool realloc_failures) { // Allocate the vframeArray vframeArray * result = (vframeArray*) AllocateHeap(sizeof(vframeArray) + // fixed part @@ -451,19 +459,20 @@ vframeArray* vframeArray::allocate(JavaThread* thread, int frame_size, GrowableA result->_caller = caller; result->_original = self; result->set_unroll_block(NULL); // initialize it - result->fill_in(thread, frame_size, chunk, reg_map); + result->fill_in(thread, frame_size, chunk, reg_map, realloc_failures); return result; } void vframeArray::fill_in(JavaThread* thread, int frame_size, GrowableArray* chunk, - const RegisterMap *reg_map) { + const RegisterMap *reg_map, + bool realloc_failures) { // Set owner first, it is used when adding monitor chunks _frame_size = frame_size; for(int i = 0; i < chunk->length(); i++) { - element(i)->fill_in(chunk->at(i)); + element(i)->fill_in(chunk->at(i), realloc_failures); } // Copy registers for callee-saved registers diff --git a/hotspot/src/share/vm/runtime/vframeArray.hpp b/hotspot/src/share/vm/runtime/vframeArray.hpp index e4665c40d36..890c386ba75 100644 --- a/hotspot/src/share/vm/runtime/vframeArray.hpp +++ b/hotspot/src/share/vm/runtime/vframeArray.hpp @@ -58,6 +58,9 @@ class vframeArrayElement : public _ValueObj { MonitorChunk* _monitors; // active monitors for this vframe StackValueCollection* _locals; StackValueCollection* _expressions; +#ifdef ASSERT + bool _removed_monitors; +#endif public: @@ -78,7 +81,7 @@ class vframeArrayElement : public _ValueObj { StackValueCollection* expressions(void) const { return _expressions; } - void fill_in(compiledVFrame* vf); + void fill_in(compiledVFrame* vf, bool realloc_failures); // Formerly part of deoptimizedVFrame @@ -99,6 +102,12 @@ class vframeArrayElement : public _ValueObj { bool is_bottom_frame, int exec_mode); +#ifdef ASSERT + void set_removed_monitors() { + _removed_monitors = true; + } +#endif + #ifndef PRODUCT void print(outputStream* st); #endif /* PRODUCT */ @@ -160,13 +169,14 @@ class vframeArray: public CHeapObj { int frames() const { return _frames; } static vframeArray* allocate(JavaThread* thread, int frame_size, GrowableArray* chunk, - RegisterMap* reg_map, frame sender, frame caller, frame self); + RegisterMap* reg_map, frame sender, frame caller, frame self, + bool realloc_failures); vframeArrayElement* element(int index) { assert(is_within_bounds(index), "Bad index"); return &_elements[index]; } // Allocates a new vframe in the array and fills the array with vframe information in chunk - void fill_in(JavaThread* thread, int frame_size, GrowableArray* chunk, const RegisterMap *reg_map); + void fill_in(JavaThread* thread, int frame_size, GrowableArray* chunk, const RegisterMap *reg_map, bool realloc_failures); // Returns the owner of this vframeArray JavaThread* owner_thread() const { return _owner_thread; } diff --git a/hotspot/src/share/vm/runtime/virtualspace.cpp b/hotspot/src/share/vm/runtime/virtualspace.cpp index ea557f338e2..1a78a53c176 100644 --- a/hotspot/src/share/vm/runtime/virtualspace.cpp +++ b/hotspot/src/share/vm/runtime/virtualspace.cpp @@ -615,19 +615,7 @@ bool VirtualSpace::expand_by(size_t bytes, bool pre_touch) { } if (pre_touch || AlwaysPreTouch) { - int vm_ps = os::vm_page_size(); - for (char* curr = previous_high; - curr < unaligned_new_high; - curr += vm_ps) { - // Note the use of a write here; originally we tried just a read, but - // since the value read was unused, the optimizer removed the read. - // If we ever have a concurrent touchahead thread, we'll want to use - // a read, to avoid the potential of overwriting data (if a mutator - // thread beats the touchahead thread to a page). There are various - // ways of making sure this read is not optimized away: for example, - // generating the code for a read procedure at runtime. - *curr = 0; - } + os::pretouch_memory(previous_high, unaligned_new_high); } _high += bytes; diff --git a/hotspot/src/share/vm/runtime/vmStructs.cpp b/hotspot/src/share/vm/runtime/vmStructs.cpp index 4df238925dd..327e0f0009c 100644 --- a/hotspot/src/share/vm/runtime/vmStructs.cpp +++ b/hotspot/src/share/vm/runtime/vmStructs.cpp @@ -556,9 +556,6 @@ typedef TwoOopHashtable SymbolTwoOopHashtable; \ nonstatic_field(TenuredGeneration, _min_heap_delta_bytes, size_t) \ nonstatic_field(TenuredGeneration, _the_space, ContiguousSpace*) \ - nonstatic_field(TenuredGeneration, _last_gc, WaterMark) \ - \ - \ \ nonstatic_field(Space, _bottom, HeapWord*) \ nonstatic_field(Space, _end, HeapWord*) \ diff --git a/hotspot/src/share/vm/runtime/vmThread.cpp b/hotspot/src/share/vm/runtime/vmThread.cpp index 274a9dfe1b3..adacb5751ce 100644 --- a/hotspot/src/share/vm/runtime/vmThread.cpp +++ b/hotspot/src/share/vm/runtime/vmThread.cpp @@ -214,7 +214,8 @@ void VMThread::create() { _vm_queue = new VMOperationQueue(); guarantee(_vm_queue != NULL, "just checking"); - _terminate_lock = new Monitor(Mutex::safepoint, "VMThread::_terminate_lock", true); + _terminate_lock = new Monitor(Mutex::safepoint, "VMThread::_terminate_lock", true, + Monitor::_safepoint_check_never); if (UsePerfData) { // jvmstat performance counters diff --git a/hotspot/src/share/vm/runtime/vm_operations.cpp b/hotspot/src/share/vm/runtime/vm_operations.cpp index efacdc7c610..208d518690e 100644 --- a/hotspot/src/share/vm/runtime/vm_operations.cpp +++ b/hotspot/src/share/vm/runtime/vm_operations.cpp @@ -391,7 +391,8 @@ int VM_Exit::wait_for_threads_in_native_to_block() { assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint already"); Thread * thr_cur = ThreadLocalStorage::get_thread_slow(); - Monitor timer(Mutex::leaf, "VM_Exit timer", true); + Monitor timer(Mutex::leaf, "VM_Exit timer", true, + Monitor::_safepoint_check_never); // Compiler threads need longer wait because they can access VM data directly // while in native. If they are active and some structures being used are diff --git a/hotspot/src/share/vm/services/diagnosticFramework.cpp b/hotspot/src/share/vm/services/diagnosticFramework.cpp index 870e6405c5b..3da2a73472a 100644 --- a/hotspot/src/share/vm/services/diagnosticFramework.cpp +++ b/hotspot/src/share/vm/services/diagnosticFramework.cpp @@ -487,7 +487,7 @@ void DCmdFactory::send_notification_internal(TRAPS) { } } -Mutex* DCmdFactory::_dcmdFactory_lock = new Mutex(Mutex::leaf, "DCmdFactory", true); +Mutex* DCmdFactory::_dcmdFactory_lock = new Mutex(Mutex::leaf, "DCmdFactory", true, Monitor::_safepoint_check_never); bool DCmdFactory::_send_jmx_notification = false; DCmdFactory* DCmdFactory::factory(DCmdSource source, const char* name, size_t len) { diff --git a/hotspot/src/share/vm/services/memoryManager.cpp b/hotspot/src/share/vm/services/memoryManager.cpp index 415c1a82855..841b771067e 100644 --- a/hotspot/src/share/vm/services/memoryManager.cpp +++ b/hotspot/src/share/vm/services/memoryManager.cpp @@ -198,7 +198,8 @@ void GCStatInfo::clear() { GCMemoryManager::GCMemoryManager() : MemoryManager() { _num_collections = 0; _last_gc_stat = NULL; - _last_gc_lock = new Mutex(Mutex::leaf, "_last_gc_lock", true); + _last_gc_lock = new Mutex(Mutex::leaf, "_last_gc_lock", true, + Monitor::_safepoint_check_never); _current_gc_stat = NULL; _num_gc_threads = 1; _notification_enabled = false; diff --git a/hotspot/src/share/vm/trace/trace.xml b/hotspot/src/share/vm/trace/trace.xml index 120d27f4d4d..fc7acd38e95 100644 --- a/hotspot/src/share/vm/trace/trace.xml +++ b/hotspot/src/share/vm/trace/trace.xml @@ -314,6 +314,28 @@ Declares a structure type that can be used in other events. + + + + + + + + + + + + + + + + + + diff --git a/hotspot/src/share/vm/utilities/decoder.cpp b/hotspot/src/share/vm/utilities/decoder.cpp index 7ed913abe60..777a98d044d 100644 --- a/hotspot/src/share/vm/utilities/decoder.cpp +++ b/hotspot/src/share/vm/utilities/decoder.cpp @@ -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 @@ -42,7 +42,9 @@ AbstractDecoder* Decoder::_shared_decoder = NULL; AbstractDecoder* Decoder::_error_handler_decoder = NULL; NullDecoder Decoder::_do_nothing_decoder; Mutex* Decoder::_shared_decoder_lock = new Mutex(Mutex::native, - "SharedDecoderLock"); + "SharedDecoderLock", + false, + Monitor::_safepoint_check_never); AbstractDecoder* Decoder::get_shared_instance() { assert(_shared_decoder_lock != NULL && _shared_decoder_lock->owned_by_self(), diff --git a/hotspot/src/share/vm/utilities/events.hpp b/hotspot/src/share/vm/utilities/events.hpp index 71a4a436694..7d929859b3d 100644 --- a/hotspot/src/share/vm/utilities/events.hpp +++ b/hotspot/src/share/vm/utilities/events.hpp @@ -90,7 +90,7 @@ template class EventLogBase : public EventLog { _length(length), _count(0), _index(0), - _mutex(Mutex::event, name) { + _mutex(Mutex::event, name, false, Monitor::_safepoint_check_never) { _records = new EventRecord[length]; } diff --git a/hotspot/src/share/vm/utilities/workgroup.cpp b/hotspot/src/share/vm/utilities/workgroup.cpp index 17db9df7a81..8e9fa51e096 100644 --- a/hotspot/src/share/vm/utilities/workgroup.cpp +++ b/hotspot/src/share/vm/utilities/workgroup.cpp @@ -46,7 +46,8 @@ AbstractWorkGang::AbstractWorkGang(const char* name, // Other initialization. _monitor = new Monitor(/* priority */ Mutex::leaf, /* name */ "WorkGroup monitor", - /* allow_vm_block */ are_GC_task_threads); + /* allow_vm_block */ are_GC_task_threads, + Monitor::_safepoint_check_sometimes); assert(monitor() != NULL, "Failed to allocate monitor"); _terminate = false; _task = NULL; @@ -378,12 +379,13 @@ const char* AbstractGangTask::name() const { // *** WorkGangBarrierSync WorkGangBarrierSync::WorkGangBarrierSync() - : _monitor(Mutex::safepoint, "work gang barrier sync", true), + : _monitor(Mutex::safepoint, "work gang barrier sync", true, + Monitor::_safepoint_check_never), _n_workers(0), _n_completed(0), _should_reset(false), _aborted(false) { } WorkGangBarrierSync::WorkGangBarrierSync(uint n_workers, const char* name) - : _monitor(Mutex::safepoint, name, true), + : _monitor(Mutex::safepoint, name, true, Monitor::_safepoint_check_never), _n_workers(n_workers), _n_completed(0), _should_reset(false), _aborted(false) { } diff --git a/hotspot/test/Makefile b/hotspot/test/Makefile index e0526fcf35c..657501a7622 100644 --- a/hotspot/test/Makefile +++ b/hotspot/test/Makefile @@ -275,6 +275,9 @@ 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) +# Multiply by 4 the timeout factor +JTREG_TIMEOUT_OPTION = -timeoutFactor:4 +JTREG_BASIC_OPTIONS += $(JTREG_TIMEOUT_OPTION) # Add any extra options JTREG_BASIC_OPTIONS += $(EXTRA_JTREG_OPTIONS) # Set other vm and test options diff --git a/hotspot/test/TEST.groups b/hotspot/test/TEST.groups index 4d1081e5363..261e0cf073c 100644 --- a/hotspot/test/TEST.groups +++ b/hotspot/test/TEST.groups @@ -50,6 +50,9 @@ # runs those tests that only require compact1 and compact2 API's. # +hotspot_all = \ + / + # Full JDK can run all tests # jdk = \ @@ -202,7 +205,6 @@ needs_compact2 = \ compact1_minimal = \ serviceability/ \ compiler/ \ - testlibrary_tests/ \ sanity/ \ runtime/ \ gc/ \ @@ -407,7 +409,9 @@ hotspot_compiler_closed = \ -closed/compiler/loopopts/8021898 hotspot_gc = \ - sanity/ExecuteInternalVMTests.java + sanity/ExecuteInternalVMTests.java \ + gc/ \ + -gc/metaspace/CompressedClassSpaceSizeInJmapHeap.java hotspot_runtime = \ runtime/ \ @@ -426,19 +430,22 @@ hotspot_runtime = \ -runtime/7158988/FieldMonitor.java hotspot_runtime_closed = \ - sanity/ExecuteInternalVMTests.java + sanity/ExecuteInternalVMTests.java \ + testlibrary_tests/TestMutuallyExclusivePlatformPredicates.java hotspot_serviceability = \ sanity/ExecuteInternalVMTests.java \ serviceability/dcmd/compiler -hotspot_all = \ +hotspot_jprt = \ + :hotspot_wbapitest \ :hotspot_compiler_1 \ :hotspot_compiler_2 \ :hotspot_compiler_3 \ :hotspot_compiler_closed \ :hotspot_gc \ :hotspot_runtime \ + :hotspot_runtime_closed \ :hotspot_serviceability #All tests that depends on nashorn extension. diff --git a/hotspot/test/compiler/arguments/BMISupportedCPUTest.java b/hotspot/test/compiler/arguments/BMISupportedCPUTest.java index df6e1540918..c67deab9bbe 100644 --- a/hotspot/test/compiler/arguments/BMISupportedCPUTest.java +++ b/hotspot/test/compiler/arguments/BMISupportedCPUTest.java @@ -60,8 +60,11 @@ public class BMISupportedCPUTest extends BMICommandLineOptionTestBase { VM will be launched with following flags: -XX:+ -version */ + String errorString = String.format("JVM should start with '-XX:+%s'" + + " flag without any warnings", optionName); CommandLineOptionTest.verifySameJVMStartup(null, - new String[] { warningMessage }, ExitCode.OK, + new String[] { warningMessage }, errorString, errorString, + ExitCode.OK, CommandLineOptionTest.prepareBooleanFlag(optionName, true)); /* @@ -69,8 +72,11 @@ public class BMISupportedCPUTest extends BMICommandLineOptionTestBase { VM will be launched with following flags: -XX:- -version */ + errorString = String.format("JVM should start with '-XX:-%s'" + + " flag without any warnings", optionName); CommandLineOptionTest.verifySameJVMStartup(null, - new String[] { warningMessage }, ExitCode.OK, + new String[] { warningMessage }, errorString, + errorString, ExitCode.OK, CommandLineOptionTest.prepareBooleanFlag(optionName, false)); /* @@ -78,7 +84,9 @@ public class BMISupportedCPUTest extends BMICommandLineOptionTestBase { VM will be launched with following flags: -version */ - CommandLineOptionTest.verifyOptionValueForSameVM(optionName, "true"); + CommandLineOptionTest.verifyOptionValueForSameVM(optionName, "true", + String.format("Option '%s' is expected to have default value " + + "'true'", optionName)); /* Verify that option could be explicitly turned off. @@ -86,6 +94,8 @@ public class BMISupportedCPUTest extends BMICommandLineOptionTestBase { -XX:- -version */ CommandLineOptionTest.verifyOptionValueForSameVM(optionName, "false", + String.format("Option '%s' is set to have value 'false'", + optionName), CommandLineOptionTest.prepareBooleanFlag(optionName, false)); } } diff --git a/hotspot/test/compiler/arguments/BMIUnsupportedCPUTest.java b/hotspot/test/compiler/arguments/BMIUnsupportedCPUTest.java index 93fbcb29687..bae0280162a 100644 --- a/hotspot/test/compiler/arguments/BMIUnsupportedCPUTest.java +++ b/hotspot/test/compiler/arguments/BMIUnsupportedCPUTest.java @@ -75,9 +75,13 @@ public class BMIUnsupportedCPUTest extends BMICommandLineOptionTestBase { warning. VM will be launched with following options: -XX:+ -version */ + String errorString = String.format("JVM should start with '-XX:+%s' " + + "flag, but output should contain warning.", optionName); CommandLineOptionTest.verifySameJVMStartup( new String[] { warningMessage }, new String[] { errorMessage }, - ExitCode.OK, CommandLineOptionTest.prepareBooleanFlag( + errorString, String.format("Option '%s' is unsupported.%n" + + "Warning expected to be shown.", optionName), ExitCode.OK, + CommandLineOptionTest.prepareBooleanFlag( optionName, true)); /* @@ -85,15 +89,21 @@ public class BMIUnsupportedCPUTest extends BMICommandLineOptionTestBase { VM will be launched with following options: -XX:- -version */ + errorString = String.format("JVM should start with '-XX:-%s' flag " + + "without any warnings", optionName); CommandLineOptionTest.verifySameJVMStartup(null, - new String[] { warningMessage, errorMessage }, ExitCode.OK, + new String[] { warningMessage, errorMessage }, + errorString, errorString, ExitCode.OK, CommandLineOptionTest.prepareBooleanFlag(optionName, false)); /* - Verify that on unsupported CPUs option is off by default. - VM will be launched with following options: -version - */ - CommandLineOptionTest.verifyOptionValueForSameVM(optionName, "false"); + * Verify that on unsupported CPUs option is off by default. VM will be + * launched with following options: -version + */ + CommandLineOptionTest.verifyOptionValueForSameVM(optionName, "false", + String.format("Option '%s' is expected to have default value " + + "'false' since feature required is not supported " + + "on CPU", optionName)); /* Verify that on unsupported CPUs option will be off even if @@ -101,6 +111,9 @@ public class BMIUnsupportedCPUTest extends BMICommandLineOptionTestBase { following options: -XX:+ -version */ CommandLineOptionTest.verifyOptionValueForSameVM(optionName, "false", + String.format("Option '%s' is expected to have default value" + + " 'false' since feature required is not supported on" + + " CPU even if user set another value.", optionName), CommandLineOptionTest.prepareBooleanFlag(optionName, true)); } @@ -118,11 +131,17 @@ public class BMIUnsupportedCPUTest extends BMICommandLineOptionTestBase { with following options: -XX:[+-] -version */ CommandLineOptionTest.verifySameJVMStartup( - new String[] { errorMessage }, null, ExitCode.FAIL, + new String[] { errorMessage }, null, + String.format("JVM startup should fail with '-XX:+%s' flag." + + "%nOption should be unknown (non-X86CPU).", + optionName), "", ExitCode.FAIL, CommandLineOptionTest.prepareBooleanFlag(optionName, true)); CommandLineOptionTest.verifySameJVMStartup( - new String[] { errorMessage }, null, ExitCode.FAIL, + new String[] { errorMessage }, null, + String.format("JVM startup should fail with '-XX:-%s' flag." + + "%nOption should be unknown (non-X86CPU)", + optionName), "", ExitCode.FAIL, CommandLineOptionTest.prepareBooleanFlag(optionName, false)); } } diff --git a/hotspot/test/compiler/arguments/CheckCompileThresholdScaling.java b/hotspot/test/compiler/arguments/CheckCompileThresholdScaling.java index fda7f666f52..b9837c2ba8d 100644 --- a/hotspot/test/compiler/arguments/CheckCompileThresholdScaling.java +++ b/hotspot/test/compiler/arguments/CheckCompileThresholdScaling.java @@ -330,7 +330,7 @@ public class CheckCompileThresholdScaling { } catch (RuntimeException e) { // Check if tiered compilation is available in this JVM // Version. Throw exception only if it is available. - if (!(tiered && out.getOutput().contains("Client VM warning: TieredCompilation is disabled in this release."))) { + if (!(tiered && out.getOutput().contains("TieredCompilation is disabled in this release."))) { throw new RuntimeException(e); } } diff --git a/hotspot/test/compiler/arguments/TestUseBMI1InstructionsOnSupportedCPU.java b/hotspot/test/compiler/arguments/TestUseBMI1InstructionsOnSupportedCPU.java index bf797b1773f..57b324fda93 100644 --- a/hotspot/test/compiler/arguments/TestUseBMI1InstructionsOnSupportedCPU.java +++ b/hotspot/test/compiler/arguments/TestUseBMI1InstructionsOnSupportedCPU.java @@ -26,7 +26,7 @@ * @bug 8031321 * @summary Verify processing of UseBMI1Instructions option on CPU with * BMI1 feature support. - * @library /testlibrary /testlibrary/whitebox + * @library /testlibrary /../../test/lib * @build TestUseBMI1InstructionsOnSupportedCPU * BMISupportedCPUTest * @run main ClassFileInstaller sun.hotspot.WhiteBox diff --git a/hotspot/test/compiler/arguments/TestUseBMI1InstructionsOnUnsupportedCPU.java b/hotspot/test/compiler/arguments/TestUseBMI1InstructionsOnUnsupportedCPU.java index 2347181043c..06dbd19c9da 100644 --- a/hotspot/test/compiler/arguments/TestUseBMI1InstructionsOnUnsupportedCPU.java +++ b/hotspot/test/compiler/arguments/TestUseBMI1InstructionsOnUnsupportedCPU.java @@ -26,7 +26,7 @@ * @bug 8031321 * @summary Verify processing of UseBMI1Instructions option on CPU without * BMI1 feature support. - * @library /testlibrary /testlibrary/whitebox + * @library /testlibrary /../../test/lib * @build TestUseBMI1InstructionsOnUnsupportedCPU * BMIUnsupportedCPUTest * @run main ClassFileInstaller sun.hotspot.WhiteBox diff --git a/hotspot/test/compiler/arguments/TestUseCountLeadingZerosInstructionOnSupportedCPU.java b/hotspot/test/compiler/arguments/TestUseCountLeadingZerosInstructionOnSupportedCPU.java index 68f2267a27c..200e6bfe9c4 100644 --- a/hotspot/test/compiler/arguments/TestUseCountLeadingZerosInstructionOnSupportedCPU.java +++ b/hotspot/test/compiler/arguments/TestUseCountLeadingZerosInstructionOnSupportedCPU.java @@ -26,7 +26,7 @@ * @bug 8031321 * @summary Verify processing of UseCountLeadingZerosInstruction option * on CPU with LZCNT support. - * @library /testlibrary /testlibrary/whitebox + * @library /testlibrary /../../test/lib * @build TestUseCountLeadingZerosInstructionOnSupportedCPU * BMISupportedCPUTest * @run main ClassFileInstaller sun.hotspot.WhiteBox diff --git a/hotspot/test/compiler/arguments/TestUseCountLeadingZerosInstructionOnUnsupportedCPU.java b/hotspot/test/compiler/arguments/TestUseCountLeadingZerosInstructionOnUnsupportedCPU.java index 68c855a78ef..74e6f626d67 100644 --- a/hotspot/test/compiler/arguments/TestUseCountLeadingZerosInstructionOnUnsupportedCPU.java +++ b/hotspot/test/compiler/arguments/TestUseCountLeadingZerosInstructionOnUnsupportedCPU.java @@ -26,7 +26,7 @@ * @bug 8031321 * @summary Verify processing of UseCountLeadingZerosInstruction option * on CPU without LZCNT support. - * @library /testlibrary /testlibrary/whitebox + * @library /testlibrary /../../test/lib * @build TestUseCountLeadingZerosInstructionOnUnsupportedCPU * BMIUnsupportedCPUTest * @run main ClassFileInstaller sun.hotspot.WhiteBox diff --git a/hotspot/test/compiler/arguments/TestUseCountTrailingZerosInstructionOnSupportedCPU.java b/hotspot/test/compiler/arguments/TestUseCountTrailingZerosInstructionOnSupportedCPU.java index 2e4400b5fe7..aadd3180d49 100644 --- a/hotspot/test/compiler/arguments/TestUseCountTrailingZerosInstructionOnSupportedCPU.java +++ b/hotspot/test/compiler/arguments/TestUseCountTrailingZerosInstructionOnSupportedCPU.java @@ -26,7 +26,7 @@ * @bug 8031321 * @summary Verify processing of UseCountTrailingZerosInstruction option * on CPU with TZCNT (BMI1 feature) support. - * @library /testlibrary /testlibrary/whitebox + * @library /testlibrary /../../test/lib * @build TestUseCountTrailingZerosInstructionOnSupportedCPU * BMISupportedCPUTest * @run main ClassFileInstaller sun.hotspot.WhiteBox @@ -59,6 +59,9 @@ public class TestUseCountTrailingZerosInstructionOnSupportedCPU -XX:-UseBMI1Instructions -version */ CommandLineOptionTest.verifyOptionValueForSameVM(optionName, "false", + "Option 'UseCountTrailingZerosInstruction' should have " + + "'false' value if all BMI1 instructions are explicitly" + + " disabled (-XX:-UseBMI1Instructions flag used)", TestUseCountTrailingZerosInstructionOnSupportedCPU.DISABLE_BMI); /* @@ -68,6 +71,9 @@ public class TestUseCountTrailingZerosInstructionOnSupportedCPU -XX:+UseCountTrailingZerosInstruction -version */ CommandLineOptionTest.verifyOptionValueForSameVM(optionName, "true", + "Option 'UseCountTrailingZerosInstruction' should be able to " + + "be turned on even if all BMI1 instructions are " + + "disabled (-XX:-UseBMI1Instructions flag used)", TestUseCountTrailingZerosInstructionOnSupportedCPU.DISABLE_BMI, CommandLineOptionTest.prepareBooleanFlag(optionName, true)); } diff --git a/hotspot/test/compiler/arguments/TestUseCountTrailingZerosInstructionOnUnsupportedCPU.java b/hotspot/test/compiler/arguments/TestUseCountTrailingZerosInstructionOnUnsupportedCPU.java index 648c112282c..68483893a53 100644 --- a/hotspot/test/compiler/arguments/TestUseCountTrailingZerosInstructionOnUnsupportedCPU.java +++ b/hotspot/test/compiler/arguments/TestUseCountTrailingZerosInstructionOnUnsupportedCPU.java @@ -26,7 +26,7 @@ * @bug 8031321 * @summary Verify processing of UseCountTrailingZerosInstruction option * on CPU without TZCNT instruction (BMI1 feature) support. - * @library /testlibrary /testlibrary/whitebox + * @library /testlibrary /../../test/lib * @build TestUseCountTrailingZerosInstructionOnUnsupportedCPU * BMIUnsupportedCPUTest * @run main ClassFileInstaller sun.hotspot.WhiteBox @@ -59,6 +59,9 @@ public class TestUseCountTrailingZerosInstructionOnUnsupportedCPU -XX:+UseBMI1Instructions -version */ CommandLineOptionTest.verifyOptionValueForSameVM(optionName, "false", + "Feature bmi1 is not supported on current CPU. Option " + + "UseCountTrailingZerosInstruction should have 'false'" + + " value", TestUseCountTrailingZerosInstructionOnUnsupportedCPU. ENABLE_BMI); @@ -68,6 +71,9 @@ public class TestUseCountTrailingZerosInstructionOnUnsupportedCPU -version */ CommandLineOptionTest.verifyOptionValueForSameVM(optionName, "false", + "Feature bmi1 is not supported on current CPU. Option " + + "UseCountTrailingZerosInstruction should have 'false'" + + " value", CommandLineOptionTest.prepareBooleanFlag(optionName, true), TestUseCountTrailingZerosInstructionOnUnsupportedCPU. ENABLE_BMI); diff --git a/hotspot/test/compiler/c2/6589834/Test_ia32.java b/hotspot/test/compiler/c2/6589834/Test_ia32.java index aed3198320d..193ca35a3f8 100644 --- a/hotspot/test/compiler/c2/6589834/Test_ia32.java +++ b/hotspot/test/compiler/c2/6589834/Test_ia32.java @@ -26,7 +26,7 @@ * @bug 6589834 * @summary Safepoint placed between stack pointer increment and decrement leads * to interpreter's stack corruption after deoptimization. - * @library /testlibrary /testlibrary/whitebox + * @library /testlibrary /../../test/lib * @build ClassFileInstaller sun.hotspot.WhiteBox com.oracle.java.testlibrary.* * Test_ia32 InlinedArrayCloneTestCase * @run main ClassFileInstaller sun.hotspot.WhiteBox diff --git a/hotspot/test/compiler/classUnloading/anonymousClass/TestAnonymousClassUnloading.java b/hotspot/test/compiler/classUnloading/anonymousClass/TestAnonymousClassUnloading.java index 6fbaf9cef72..d6c3ed05d0c 100644 --- a/hotspot/test/compiler/classUnloading/anonymousClass/TestAnonymousClassUnloading.java +++ b/hotspot/test/compiler/classUnloading/anonymousClass/TestAnonymousClassUnloading.java @@ -33,7 +33,7 @@ import java.net.URLConnection; * @test TestAnonymousClassUnloading * @bug 8054402 * @summary "Tests unloading of anonymous classes." - * @library /testlibrary /testlibrary/whitebox + * @library /testlibrary /../../test/lib * @compile TestAnonymousClassUnloading.java * @run main ClassFileInstaller TestAnonymousClassUnloading * sun.hotspot.WhiteBox diff --git a/hotspot/test/compiler/classUnloading/methodUnloading/TestMethodUnloading.java b/hotspot/test/compiler/classUnloading/methodUnloading/TestMethodUnloading.java index 9e7a19b69aa..d2cf51ee8bd 100644 --- a/hotspot/test/compiler/classUnloading/methodUnloading/TestMethodUnloading.java +++ b/hotspot/test/compiler/classUnloading/methodUnloading/TestMethodUnloading.java @@ -31,7 +31,7 @@ import java.net.URLClassLoader; * @test MethodUnloadingTest * @bug 8029443 * @summary "Tests the unloading of methods to to class unloading" - * @library /testlibrary /testlibrary/whitebox + * @library /testlibrary /../../test/lib * @build TestMethodUnloading * @build WorkerClass * @run main ClassFileInstaller sun.hotspot.WhiteBox diff --git a/hotspot/test/compiler/codecache/CheckSegmentedCodeCache.java b/hotspot/test/compiler/codecache/CheckSegmentedCodeCache.java index da739765bea..654293be030 100644 --- a/hotspot/test/compiler/codecache/CheckSegmentedCodeCache.java +++ b/hotspot/test/compiler/codecache/CheckSegmentedCodeCache.java @@ -27,7 +27,7 @@ import sun.hotspot.WhiteBox; /* * @test CheckSegmentedCodeCache * @bug 8015774 - * @library /testlibrary /testlibrary/whitebox + * @library /testlibrary /../../test/lib * @summary "Checks VM options related to the segmented code cache" * @build CheckSegmentedCodeCache * @run main ClassFileInstaller sun.hotspot.WhiteBox diff --git a/hotspot/test/compiler/codecache/OverflowCodeCacheTest.java b/hotspot/test/compiler/codecache/OverflowCodeCacheTest.java index c772f4fbddc..5ee28556505 100644 --- a/hotspot/test/compiler/codecache/OverflowCodeCacheTest.java +++ b/hotspot/test/compiler/codecache/OverflowCodeCacheTest.java @@ -34,7 +34,7 @@ import com.oracle.java.testlibrary.Asserts; /* * @test OverflowCodeCacheTest * @bug 8059550 - * @library /testlibrary /testlibrary/whitebox + * @library /testlibrary /../../test/lib * @build OverflowCodeCacheTest * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/compiler/dependencies/MonomorphicObjectCall/TestMonomorphicObjectCall.java b/hotspot/test/compiler/dependencies/MonomorphicObjectCall/TestMonomorphicObjectCall.java index 932599013cf..8884ce404c5 100644 --- a/hotspot/test/compiler/dependencies/MonomorphicObjectCall/TestMonomorphicObjectCall.java +++ b/hotspot/test/compiler/dependencies/MonomorphicObjectCall/TestMonomorphicObjectCall.java @@ -61,6 +61,7 @@ public class TestMonomorphicObjectCall { String[] vmOpts = new String[] { "-Xbootclasspath/p:" + testClasses, "-Xcomp", + "-XX:+IgnoreUnrecognizedVMOptions", "-XX:-VerifyDependencies", "-XX:CompileOnly=TestMonomorphicObjectCall::callFinalize", "-XX:CompileOnly=Object::finalizeObject", diff --git a/hotspot/test/compiler/exceptions/SumTest.java b/hotspot/test/compiler/exceptions/SumTest.java new file mode 100644 index 00000000000..d4555aa55aa --- /dev/null +++ b/hotspot/test/compiler/exceptions/SumTest.java @@ -0,0 +1,86 @@ +/* + * 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 8066900 + * @summary FP registers are not properly restored by C1 when handling exceptions + * @run main/othervm -Xbatch SumTest + * + */ +public class SumTest { + private static class Sum { + + double[] sums; + + /** + * Construct empty Sum + */ + public Sum() { + sums = new double[0]; + } + + /** + * Return the sum of all numbers added to this Sum + * + * @return the sum + */ + final public double getSum() { + double sum = 0; + for (final double s : sums) { + sum += s; + } + + return sum; + } + + /** + * Add a new number to this Sum + * + * @param a number to be added. + */ + final public void add(double a) { + try { + sums[sums.length] = -1; // Cause IndexOutOfBoundsException + } catch (final IndexOutOfBoundsException e) { + final double[] oldSums = sums; + sums = new double[oldSums.length + 1]; // Extend sums + System.arraycopy(oldSums, 0, sums, 0, oldSums.length); + sums[oldSums.length] = a; // Append a + } + } + } + + public static void main(String[] args) throws Exception { + final Sum sum = new Sum(); + for (int i = 1; i <= 10000; ++i) { + sum.add(1); + double ii = sum.getSum(); + if (i != ii) { + throw new Exception("Failure: computed = " + ii + ", expected = " + i); + } + } + } + +} + diff --git a/hotspot/test/compiler/intrinsics/bmi/TestAndnI.java b/hotspot/test/compiler/intrinsics/bmi/TestAndnI.java index fa7b842380e..84d32ffae41 100644 --- a/hotspot/test/compiler/intrinsics/bmi/TestAndnI.java +++ b/hotspot/test/compiler/intrinsics/bmi/TestAndnI.java @@ -27,7 +27,7 @@ * @bug 8031321 * @summary Verify that results of computations are the same w/ * and w/o usage of ANDN instruction - * @library /testlibrary /testlibrary/whitebox + * @library /testlibrary /../../test/lib * @build TestAndnI BMITestRunner Expr * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/compiler/intrinsics/bmi/TestAndnL.java b/hotspot/test/compiler/intrinsics/bmi/TestAndnL.java index 6e7fbe4fbf8..d6b33a6f079 100644 --- a/hotspot/test/compiler/intrinsics/bmi/TestAndnL.java +++ b/hotspot/test/compiler/intrinsics/bmi/TestAndnL.java @@ -27,7 +27,7 @@ * @bug 8031321 * @summary Verify that results of computations are the same w/ * and w/o usage of ANDN instruction - * @library /testlibrary /testlibrary/whitebox + * @library /testlibrary /../../test/lib * @build TestAndnL BMITestRunner Expr * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/compiler/intrinsics/bmi/TestBlsiI.java b/hotspot/test/compiler/intrinsics/bmi/TestBlsiI.java index 794676252a0..d8dfc41b6db 100644 --- a/hotspot/test/compiler/intrinsics/bmi/TestBlsiI.java +++ b/hotspot/test/compiler/intrinsics/bmi/TestBlsiI.java @@ -27,7 +27,7 @@ * @bug 8031321 * @summary Verify that results of computations are the same w/ * and w/o usage of BLSI instruction - * @library /testlibrary /testlibrary/whitebox + * @library /testlibrary /../../test/lib * @build TestBlsiI BMITestRunner Expr * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/compiler/intrinsics/bmi/TestBlsiL.java b/hotspot/test/compiler/intrinsics/bmi/TestBlsiL.java index 046351222e9..9e0cd016dda 100644 --- a/hotspot/test/compiler/intrinsics/bmi/TestBlsiL.java +++ b/hotspot/test/compiler/intrinsics/bmi/TestBlsiL.java @@ -27,7 +27,7 @@ * @bug 8031321 * @summary Verify that results of computations are the same w/ * and w/o usage of BLSI instruction - * @library /testlibrary /testlibrary/whitebox + * @library /testlibrary /../../test/lib * @build TestBlsiL BMITestRunner Expr * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/compiler/intrinsics/bmi/TestBlsmskI.java b/hotspot/test/compiler/intrinsics/bmi/TestBlsmskI.java index 3f1b95ffec2..869aff8c230 100644 --- a/hotspot/test/compiler/intrinsics/bmi/TestBlsmskI.java +++ b/hotspot/test/compiler/intrinsics/bmi/TestBlsmskI.java @@ -27,7 +27,7 @@ * @bug 8031321 * @summary Verify that results of computations are the same w/ * and w/o usage of BLSMSK instruction - * @library /testlibrary /testlibrary/whitebox + * @library /testlibrary /../../test/lib * @build TestBlsmskI BMITestRunner Expr * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/compiler/intrinsics/bmi/TestBlsmskL.java b/hotspot/test/compiler/intrinsics/bmi/TestBlsmskL.java index aca3981f779..2e8d8ae7d0e 100644 --- a/hotspot/test/compiler/intrinsics/bmi/TestBlsmskL.java +++ b/hotspot/test/compiler/intrinsics/bmi/TestBlsmskL.java @@ -27,7 +27,7 @@ * @bug 8031321 * @summary Verify that results of computations are the same w/ * and w/o usage of BLSMSK instruction - * @library /testlibrary /testlibrary/whitebox + * @library /testlibrary /../../test/lib * @build TestBlsmskL BMITestRunner Expr * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/compiler/intrinsics/bmi/TestBlsrI.java b/hotspot/test/compiler/intrinsics/bmi/TestBlsrI.java index 90121c88942..f9dc1928497 100644 --- a/hotspot/test/compiler/intrinsics/bmi/TestBlsrI.java +++ b/hotspot/test/compiler/intrinsics/bmi/TestBlsrI.java @@ -27,7 +27,7 @@ * @bug 8031321 * @summary Verify that results of computations are the same w/ * and w/o usage of BLSR instruction - * @library /testlibrary /testlibrary/whitebox + * @library /testlibrary /../../test/lib * @build TestBlsrI BMITestRunner Expr * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/compiler/intrinsics/bmi/TestBlsrL.java b/hotspot/test/compiler/intrinsics/bmi/TestBlsrL.java index ad267769dac..c6c2f2d401f 100644 --- a/hotspot/test/compiler/intrinsics/bmi/TestBlsrL.java +++ b/hotspot/test/compiler/intrinsics/bmi/TestBlsrL.java @@ -27,7 +27,7 @@ * @bug 8031321 * @summary Verify that results of computations are the same w/ * and w/o usage of BLSR instruction - * @library /testlibrary /testlibrary/whitebox + * @library /testlibrary /../../test/lib * @build TestBlsrL BMITestRunner Expr * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/compiler/intrinsics/bmi/TestLzcntI.java b/hotspot/test/compiler/intrinsics/bmi/TestLzcntI.java index 5cb08e0a381..acd1b1628cd 100644 --- a/hotspot/test/compiler/intrinsics/bmi/TestLzcntI.java +++ b/hotspot/test/compiler/intrinsics/bmi/TestLzcntI.java @@ -27,7 +27,7 @@ * @bug 8031321 * @summary Verify that results of computations are the same w/ * and w/o usage of intrinsic - * @library /testlibrary /testlibrary/whitebox + * @library /testlibrary /../../test/lib * @build TestLzcntI BMITestRunner Expr * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/compiler/intrinsics/bmi/TestLzcntL.java b/hotspot/test/compiler/intrinsics/bmi/TestLzcntL.java index fbcadf49dad..63891cdef67 100644 --- a/hotspot/test/compiler/intrinsics/bmi/TestLzcntL.java +++ b/hotspot/test/compiler/intrinsics/bmi/TestLzcntL.java @@ -27,7 +27,7 @@ * @bug 8031321 * @summary Verify that results of computations are the same w/ * and w/o usage of intrinsic - * @library /testlibrary /testlibrary/whitebox + * @library /testlibrary /../../test/lib * @build TestLzcntL BMITestRunner Expr * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/compiler/intrinsics/bmi/TestTzcntI.java b/hotspot/test/compiler/intrinsics/bmi/TestTzcntI.java index bd8c8764617..6e4894a968a 100644 --- a/hotspot/test/compiler/intrinsics/bmi/TestTzcntI.java +++ b/hotspot/test/compiler/intrinsics/bmi/TestTzcntI.java @@ -27,7 +27,7 @@ * @bug 8031321 * @summary Verify that results of computations are the same w/ * and w/o usage of intrinsic - * @library /testlibrary /testlibrary/whitebox + * @library /testlibrary /../../test/lib * @build TestTzcntI BMITestRunner Expr * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/compiler/intrinsics/bmi/TestTzcntL.java b/hotspot/test/compiler/intrinsics/bmi/TestTzcntL.java index 0a008aa4d58..d2f634cb498 100644 --- a/hotspot/test/compiler/intrinsics/bmi/TestTzcntL.java +++ b/hotspot/test/compiler/intrinsics/bmi/TestTzcntL.java @@ -27,7 +27,7 @@ * @bug 8031321 * @summary Verify that results of computations are the same w/ * and w/o usage of intrinsic - * @library /testlibrary /testlibrary/whitebox + * @library /testlibrary /../../test/lib * @build TestTzcntL BMITestRunner Expr * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/compiler/intrinsics/bmi/verifycode/AddnTestI.java b/hotspot/test/compiler/intrinsics/bmi/verifycode/AddnTestI.java index 3b6f2f3ee20..ea9e6df5abe 100644 --- a/hotspot/test/compiler/intrinsics/bmi/verifycode/AddnTestI.java +++ b/hotspot/test/compiler/intrinsics/bmi/verifycode/AddnTestI.java @@ -24,7 +24,7 @@ /* * @test * @bug 8031321 - * @library /testlibrary /testlibrary/whitebox /compiler/whitebox .. + * @library /testlibrary /../../test/lib /compiler/whitebox .. * @build AddnTestI * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/compiler/intrinsics/bmi/verifycode/AddnTestL.java b/hotspot/test/compiler/intrinsics/bmi/verifycode/AddnTestL.java index c03469361b7..0859ba15523 100644 --- a/hotspot/test/compiler/intrinsics/bmi/verifycode/AddnTestL.java +++ b/hotspot/test/compiler/intrinsics/bmi/verifycode/AddnTestL.java @@ -24,7 +24,7 @@ /* * @test * @bug 8031321 - * @library /testlibrary /testlibrary/whitebox /compiler/whitebox .. + * @library /testlibrary /../../test/lib /compiler/whitebox .. * @build AddnTestL * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/compiler/intrinsics/bmi/verifycode/BlsiTestI.java b/hotspot/test/compiler/intrinsics/bmi/verifycode/BlsiTestI.java index 92a87875a5c..8a6aa8b69f3 100644 --- a/hotspot/test/compiler/intrinsics/bmi/verifycode/BlsiTestI.java +++ b/hotspot/test/compiler/intrinsics/bmi/verifycode/BlsiTestI.java @@ -24,7 +24,7 @@ /* * @test * @bug 8031321 - * @library /testlibrary /testlibrary/whitebox /compiler/whitebox .. + * @library /testlibrary /../../test/lib /compiler/whitebox .. * @build BlsiTestI * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/compiler/intrinsics/bmi/verifycode/BlsiTestL.java b/hotspot/test/compiler/intrinsics/bmi/verifycode/BlsiTestL.java index 2894a53b406..9b087263b48 100644 --- a/hotspot/test/compiler/intrinsics/bmi/verifycode/BlsiTestL.java +++ b/hotspot/test/compiler/intrinsics/bmi/verifycode/BlsiTestL.java @@ -24,7 +24,7 @@ /* * @test * @bug 8031321 - * @library /testlibrary /testlibrary/whitebox /compiler/whitebox .. + * @library /testlibrary /../../test/lib /compiler/whitebox .. * @build BlsiTestL * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/compiler/intrinsics/bmi/verifycode/BlsmskTestI.java b/hotspot/test/compiler/intrinsics/bmi/verifycode/BlsmskTestI.java index 2f0be6af7bf..31c747ea531 100644 --- a/hotspot/test/compiler/intrinsics/bmi/verifycode/BlsmskTestI.java +++ b/hotspot/test/compiler/intrinsics/bmi/verifycode/BlsmskTestI.java @@ -24,7 +24,7 @@ /* * @test * @bug 8031321 - * @library /testlibrary /testlibrary/whitebox /compiler/whitebox .. + * @library /testlibrary /../../test/lib /compiler/whitebox .. * @build BlsmskTestI * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/compiler/intrinsics/bmi/verifycode/BlsmskTestL.java b/hotspot/test/compiler/intrinsics/bmi/verifycode/BlsmskTestL.java index f2b7345b582..07887bcaac7 100644 --- a/hotspot/test/compiler/intrinsics/bmi/verifycode/BlsmskTestL.java +++ b/hotspot/test/compiler/intrinsics/bmi/verifycode/BlsmskTestL.java @@ -24,7 +24,7 @@ /* * @test * @bug 8031321 - * @library /testlibrary /testlibrary/whitebox /compiler/whitebox .. + * @library /testlibrary /../../test/lib /compiler/whitebox .. * @build BlsmskTestL * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/compiler/intrinsics/bmi/verifycode/BlsrTestI.java b/hotspot/test/compiler/intrinsics/bmi/verifycode/BlsrTestI.java index 67d1b90dcee..2424d936b99 100644 --- a/hotspot/test/compiler/intrinsics/bmi/verifycode/BlsrTestI.java +++ b/hotspot/test/compiler/intrinsics/bmi/verifycode/BlsrTestI.java @@ -24,7 +24,7 @@ /* * @test * @bug 8031321 - * @library /testlibrary /testlibrary/whitebox /compiler/whitebox .. + * @library /testlibrary /../../test/lib /compiler/whitebox .. * @build BlsrTestI * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/compiler/intrinsics/bmi/verifycode/BlsrTestL.java b/hotspot/test/compiler/intrinsics/bmi/verifycode/BlsrTestL.java index 158f3440663..050520367ba 100644 --- a/hotspot/test/compiler/intrinsics/bmi/verifycode/BlsrTestL.java +++ b/hotspot/test/compiler/intrinsics/bmi/verifycode/BlsrTestL.java @@ -24,7 +24,7 @@ /* * @test * @bug 8031321 - * @library /testlibrary /testlibrary/whitebox /compiler/whitebox .. + * @library /testlibrary /../../test/lib /compiler/whitebox .. * @build BlsrTestL * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/compiler/intrinsics/bmi/verifycode/LZcntTestI.java b/hotspot/test/compiler/intrinsics/bmi/verifycode/LZcntTestI.java index d74c19ac107..46892c7bb3f 100644 --- a/hotspot/test/compiler/intrinsics/bmi/verifycode/LZcntTestI.java +++ b/hotspot/test/compiler/intrinsics/bmi/verifycode/LZcntTestI.java @@ -24,7 +24,7 @@ /* * @test * @bug 8031321 - * @library /testlibrary /testlibrary/whitebox /compiler/whitebox .. + * @library /testlibrary /../../test/lib /compiler/whitebox .. * @build LZcntTestI * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/compiler/intrinsics/bmi/verifycode/LZcntTestL.java b/hotspot/test/compiler/intrinsics/bmi/verifycode/LZcntTestL.java index 5c164ff8ac9..64002d93876 100644 --- a/hotspot/test/compiler/intrinsics/bmi/verifycode/LZcntTestL.java +++ b/hotspot/test/compiler/intrinsics/bmi/verifycode/LZcntTestL.java @@ -24,7 +24,7 @@ /* * @test * @bug 8031321 - * @library /testlibrary /testlibrary/whitebox /compiler/whitebox .. + * @library /testlibrary /../../test/lib /compiler/whitebox .. * @build LZcntTestL * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/compiler/intrinsics/bmi/verifycode/TZcntTestI.java b/hotspot/test/compiler/intrinsics/bmi/verifycode/TZcntTestI.java index 7fa47ba03e2..d9669f69745 100644 --- a/hotspot/test/compiler/intrinsics/bmi/verifycode/TZcntTestI.java +++ b/hotspot/test/compiler/intrinsics/bmi/verifycode/TZcntTestI.java @@ -24,7 +24,7 @@ /* * @test * @bug 8031321 - * @library /testlibrary /testlibrary/whitebox /compiler/whitebox .. + * @library /testlibrary /../../test/lib /compiler/whitebox .. * @build TZcntTestI * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/compiler/intrinsics/bmi/verifycode/TZcntTestL.java b/hotspot/test/compiler/intrinsics/bmi/verifycode/TZcntTestL.java index e06f9ddb0b1..7ba85b3c3de 100644 --- a/hotspot/test/compiler/intrinsics/bmi/verifycode/TZcntTestL.java +++ b/hotspot/test/compiler/intrinsics/bmi/verifycode/TZcntTestL.java @@ -24,7 +24,7 @@ /* * @test * @bug 8031321 - * @library /testlibrary /testlibrary/whitebox /compiler/whitebox .. + * @library /testlibrary /../../test/lib /compiler/whitebox .. * @build TZcntTestL * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/compiler/intrinsics/classcast/NullCheckDroppingsTest.java b/hotspot/test/compiler/intrinsics/classcast/NullCheckDroppingsTest.java index 9f88fe44f70..9e05df15341 100644 --- a/hotspot/test/compiler/intrinsics/classcast/NullCheckDroppingsTest.java +++ b/hotspot/test/compiler/intrinsics/classcast/NullCheckDroppingsTest.java @@ -25,7 +25,7 @@ * @test NullCheckDroppingsTest * @bug 8054492 * @summary "Casting can result in redundant null checks in generated code" - * @library /testlibrary /testlibrary/whitebox /testlibrary/com/oracle/java/testlibrary + * @library /testlibrary /../../test/lib /testlibrary/com/oracle/java/testlibrary * @build NullCheckDroppingsTest * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/compiler/intrinsics/mathexact/sanity/AddExactIntTest.java b/hotspot/test/compiler/intrinsics/mathexact/sanity/AddExactIntTest.java index e0010c2a8f1..5db9df2cbf1 100644 --- a/hotspot/test/compiler/intrinsics/mathexact/sanity/AddExactIntTest.java +++ b/hotspot/test/compiler/intrinsics/mathexact/sanity/AddExactIntTest.java @@ -23,7 +23,7 @@ /* * @test - * @library /testlibrary /testlibrary/whitebox /compiler/whitebox + * @library /testlibrary /../../test/lib /compiler/whitebox * /compiler/testlibrary * @build AddExactIntTest * @run main ClassFileInstaller sun.hotspot.WhiteBox diff --git a/hotspot/test/compiler/intrinsics/mathexact/sanity/AddExactLongTest.java b/hotspot/test/compiler/intrinsics/mathexact/sanity/AddExactLongTest.java index 38efa5d3867..7b68e7072d3 100644 --- a/hotspot/test/compiler/intrinsics/mathexact/sanity/AddExactLongTest.java +++ b/hotspot/test/compiler/intrinsics/mathexact/sanity/AddExactLongTest.java @@ -23,7 +23,7 @@ /* * @test - * @library /testlibrary /testlibrary/whitebox /compiler/whitebox + * @library /testlibrary /../../test/lib /compiler/whitebox * /compiler/testlibrary * @build AddExactLongTest * @run main ClassFileInstaller sun.hotspot.WhiteBox diff --git a/hotspot/test/compiler/intrinsics/mathexact/sanity/DecrementExactIntTest.java b/hotspot/test/compiler/intrinsics/mathexact/sanity/DecrementExactIntTest.java index be55af8c02f..a261d4cf1f2 100644 --- a/hotspot/test/compiler/intrinsics/mathexact/sanity/DecrementExactIntTest.java +++ b/hotspot/test/compiler/intrinsics/mathexact/sanity/DecrementExactIntTest.java @@ -23,7 +23,7 @@ /* * @test - * @library /testlibrary /testlibrary/whitebox /compiler/whitebox + * @library /testlibrary /../../test/lib /compiler/whitebox * /compiler/testlibrary * @build DecrementExactIntTest * @run main ClassFileInstaller sun.hotspot.WhiteBox diff --git a/hotspot/test/compiler/intrinsics/mathexact/sanity/DecrementExactLongTest.java b/hotspot/test/compiler/intrinsics/mathexact/sanity/DecrementExactLongTest.java index 8a48401c712..527bdc769fe 100644 --- a/hotspot/test/compiler/intrinsics/mathexact/sanity/DecrementExactLongTest.java +++ b/hotspot/test/compiler/intrinsics/mathexact/sanity/DecrementExactLongTest.java @@ -23,7 +23,7 @@ /* * @test - * @library /testlibrary /testlibrary/whitebox /compiler/whitebox + * @library /testlibrary /../../test/lib /compiler/whitebox * /compiler/testlibrary * @build DecrementExactLongTest * @run main ClassFileInstaller sun.hotspot.WhiteBox diff --git a/hotspot/test/compiler/intrinsics/mathexact/sanity/IncrementExactIntTest.java b/hotspot/test/compiler/intrinsics/mathexact/sanity/IncrementExactIntTest.java index 657a3f7723d..dee345c22ae 100644 --- a/hotspot/test/compiler/intrinsics/mathexact/sanity/IncrementExactIntTest.java +++ b/hotspot/test/compiler/intrinsics/mathexact/sanity/IncrementExactIntTest.java @@ -23,7 +23,7 @@ /* * @test - * @library /testlibrary /testlibrary/whitebox /compiler/whitebox + * @library /testlibrary /../../test/lib /compiler/whitebox * /compiler/testlibrary * @build IncrementExactIntTest * @run main ClassFileInstaller sun.hotspot.WhiteBox diff --git a/hotspot/test/compiler/intrinsics/mathexact/sanity/IncrementExactLongTest.java b/hotspot/test/compiler/intrinsics/mathexact/sanity/IncrementExactLongTest.java index 7915f9fd028..e72ebb2dbc2 100644 --- a/hotspot/test/compiler/intrinsics/mathexact/sanity/IncrementExactLongTest.java +++ b/hotspot/test/compiler/intrinsics/mathexact/sanity/IncrementExactLongTest.java @@ -23,7 +23,7 @@ /* * @test - * @library /testlibrary /testlibrary/whitebox /compiler/whitebox + * @library /testlibrary /../../test/lib /compiler/whitebox * /compiler/testlibrary * @build IncrementExactLongTest * @run main ClassFileInstaller sun.hotspot.WhiteBox diff --git a/hotspot/test/compiler/intrinsics/mathexact/sanity/MultiplyExactIntTest.java b/hotspot/test/compiler/intrinsics/mathexact/sanity/MultiplyExactIntTest.java index d192f66469a..195c00dd708 100644 --- a/hotspot/test/compiler/intrinsics/mathexact/sanity/MultiplyExactIntTest.java +++ b/hotspot/test/compiler/intrinsics/mathexact/sanity/MultiplyExactIntTest.java @@ -23,7 +23,7 @@ /* * @test - * @library /testlibrary /testlibrary/whitebox /compiler/whitebox + * @library /testlibrary /../../test/lib /compiler/whitebox * /compiler/testlibrary * @build MultiplyExactIntTest * @run main ClassFileInstaller sun.hotspot.WhiteBox diff --git a/hotspot/test/compiler/intrinsics/mathexact/sanity/MultiplyExactLongTest.java b/hotspot/test/compiler/intrinsics/mathexact/sanity/MultiplyExactLongTest.java index bbca388fc01..3773000bc16 100644 --- a/hotspot/test/compiler/intrinsics/mathexact/sanity/MultiplyExactLongTest.java +++ b/hotspot/test/compiler/intrinsics/mathexact/sanity/MultiplyExactLongTest.java @@ -23,7 +23,7 @@ /* * @test - * @library /testlibrary /testlibrary/whitebox /compiler/whitebox + * @library /testlibrary /../../test/lib /compiler/whitebox * /compiler/testlibrary * @build MultiplyExactLongTest * @run main ClassFileInstaller sun.hotspot.WhiteBox diff --git a/hotspot/test/compiler/intrinsics/mathexact/sanity/NegateExactIntTest.java b/hotspot/test/compiler/intrinsics/mathexact/sanity/NegateExactIntTest.java index a8a1def13b5..1151cf03fde 100644 --- a/hotspot/test/compiler/intrinsics/mathexact/sanity/NegateExactIntTest.java +++ b/hotspot/test/compiler/intrinsics/mathexact/sanity/NegateExactIntTest.java @@ -23,7 +23,7 @@ /* * @test - * @library /testlibrary /testlibrary/whitebox /compiler/whitebox + * @library /testlibrary /../../test/lib /compiler/whitebox * /compiler/testlibrary * @build NegateExactIntTest * @run main ClassFileInstaller sun.hotspot.WhiteBox diff --git a/hotspot/test/compiler/intrinsics/mathexact/sanity/NegateExactLongTest.java b/hotspot/test/compiler/intrinsics/mathexact/sanity/NegateExactLongTest.java index ebdbdcca07b..c54ce3b6359 100644 --- a/hotspot/test/compiler/intrinsics/mathexact/sanity/NegateExactLongTest.java +++ b/hotspot/test/compiler/intrinsics/mathexact/sanity/NegateExactLongTest.java @@ -23,7 +23,7 @@ /* * @test - * @library /testlibrary /testlibrary/whitebox /compiler/whitebox + * @library /testlibrary /../../test/lib /compiler/whitebox * /compiler/testlibrary * @build NegateExactLongTest * @run main ClassFileInstaller sun.hotspot.WhiteBox diff --git a/hotspot/test/compiler/intrinsics/mathexact/sanity/SubtractExactIntTest.java b/hotspot/test/compiler/intrinsics/mathexact/sanity/SubtractExactIntTest.java index e3f7c460de9..c9d9bacdd39 100644 --- a/hotspot/test/compiler/intrinsics/mathexact/sanity/SubtractExactIntTest.java +++ b/hotspot/test/compiler/intrinsics/mathexact/sanity/SubtractExactIntTest.java @@ -23,7 +23,7 @@ /* * @test - * @library /testlibrary /testlibrary/whitebox /compiler/whitebox + * @library /testlibrary /../../test/lib /compiler/whitebox * /compiler/testlibrary * @build SubtractExactIntTest * @run main ClassFileInstaller sun.hotspot.WhiteBox diff --git a/hotspot/test/compiler/intrinsics/mathexact/sanity/SubtractExactLongTest.java b/hotspot/test/compiler/intrinsics/mathexact/sanity/SubtractExactLongTest.java index ddb28fc0ee4..ca61982eb57 100644 --- a/hotspot/test/compiler/intrinsics/mathexact/sanity/SubtractExactLongTest.java +++ b/hotspot/test/compiler/intrinsics/mathexact/sanity/SubtractExactLongTest.java @@ -23,7 +23,7 @@ /* * @test - * @library /testlibrary /testlibrary/whitebox /compiler/whitebox + * @library /testlibrary /../../test/lib /compiler/whitebox * /compiler/testlibrary * @build SubtractExactLongTest * @run main ClassFileInstaller sun.hotspot.WhiteBox diff --git a/hotspot/test/compiler/intrinsics/sha/cli/TestUseSHA1IntrinsicsOptionOnSupportedCPU.java b/hotspot/test/compiler/intrinsics/sha/cli/TestUseSHA1IntrinsicsOptionOnSupportedCPU.java index 7f0d86f0be4..ce6de958285 100644 --- a/hotspot/test/compiler/intrinsics/sha/cli/TestUseSHA1IntrinsicsOptionOnSupportedCPU.java +++ b/hotspot/test/compiler/intrinsics/sha/cli/TestUseSHA1IntrinsicsOptionOnSupportedCPU.java @@ -25,7 +25,7 @@ * @test * @bug 8035968 * @summary Verify UseSHA1Intrinsics option processing on supported CPU, - * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary testcases + * @library /testlibrary /../../test/lib /compiler/testlibrary testcases * @build TestUseSHA1IntrinsicsOptionOnSupportedCPU * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/compiler/intrinsics/sha/cli/TestUseSHA1IntrinsicsOptionOnUnsupportedCPU.java b/hotspot/test/compiler/intrinsics/sha/cli/TestUseSHA1IntrinsicsOptionOnUnsupportedCPU.java index 62cf37f1e35..097d3b2872f 100644 --- a/hotspot/test/compiler/intrinsics/sha/cli/TestUseSHA1IntrinsicsOptionOnUnsupportedCPU.java +++ b/hotspot/test/compiler/intrinsics/sha/cli/TestUseSHA1IntrinsicsOptionOnUnsupportedCPU.java @@ -25,7 +25,7 @@ * @test * @bug 8035968 * @summary Verify UseSHA1Intrinsics option processing on unsupported CPU, - * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary testcases + * @library /testlibrary /../../test/lib /compiler/testlibrary testcases * @build TestUseSHA1IntrinsicsOptionOnUnsupportedCPU * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/compiler/intrinsics/sha/cli/TestUseSHA256IntrinsicsOptionOnSupportedCPU.java b/hotspot/test/compiler/intrinsics/sha/cli/TestUseSHA256IntrinsicsOptionOnSupportedCPU.java index c36efe92163..576b3e9d593 100644 --- a/hotspot/test/compiler/intrinsics/sha/cli/TestUseSHA256IntrinsicsOptionOnSupportedCPU.java +++ b/hotspot/test/compiler/intrinsics/sha/cli/TestUseSHA256IntrinsicsOptionOnSupportedCPU.java @@ -25,7 +25,7 @@ * @test * @bug 8035968 * @summary Verify UseSHA256Intrinsics option processing on supported CPU, - * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary testcases + * @library /testlibrary /../../test/lib /compiler/testlibrary testcases * @build TestUseSHA256IntrinsicsOptionOnSupportedCPU * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/compiler/intrinsics/sha/cli/TestUseSHA256IntrinsicsOptionOnUnsupportedCPU.java b/hotspot/test/compiler/intrinsics/sha/cli/TestUseSHA256IntrinsicsOptionOnUnsupportedCPU.java index b14c9c2c719..37c76b866ea 100644 --- a/hotspot/test/compiler/intrinsics/sha/cli/TestUseSHA256IntrinsicsOptionOnUnsupportedCPU.java +++ b/hotspot/test/compiler/intrinsics/sha/cli/TestUseSHA256IntrinsicsOptionOnUnsupportedCPU.java @@ -25,7 +25,7 @@ * @test * @bug 8035968 * @summary Verify UseSHA256Intrinsics option processing on unsupported CPU, - * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary testcases + * @library /testlibrary /../../test/lib /compiler/testlibrary testcases * @build TestUseSHA256IntrinsicsOptionOnUnsupportedCPU * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/compiler/intrinsics/sha/cli/TestUseSHA512IntrinsicsOptionOnSupportedCPU.java b/hotspot/test/compiler/intrinsics/sha/cli/TestUseSHA512IntrinsicsOptionOnSupportedCPU.java index 66e7f4a1ef1..f030e3fe851 100644 --- a/hotspot/test/compiler/intrinsics/sha/cli/TestUseSHA512IntrinsicsOptionOnSupportedCPU.java +++ b/hotspot/test/compiler/intrinsics/sha/cli/TestUseSHA512IntrinsicsOptionOnSupportedCPU.java @@ -25,7 +25,7 @@ * @test * @bug 8035968 * @summary Verify UseSHA512Intrinsics option processing on supported CPU. - * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary testcases + * @library /testlibrary /../../test/lib /compiler/testlibrary testcases * @build TestUseSHA512IntrinsicsOptionOnSupportedCPU * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/compiler/intrinsics/sha/cli/TestUseSHA512IntrinsicsOptionOnUnsupportedCPU.java b/hotspot/test/compiler/intrinsics/sha/cli/TestUseSHA512IntrinsicsOptionOnUnsupportedCPU.java index 22d4d36ffde..2c6fb68bd07 100644 --- a/hotspot/test/compiler/intrinsics/sha/cli/TestUseSHA512IntrinsicsOptionOnUnsupportedCPU.java +++ b/hotspot/test/compiler/intrinsics/sha/cli/TestUseSHA512IntrinsicsOptionOnUnsupportedCPU.java @@ -25,7 +25,7 @@ * @test * @bug 8035968 * @summary Verify UseSHA512Intrinsics option processing on unsupported CPU, - * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary testcases + * @library /testlibrary /../../test/lib /compiler/testlibrary testcases * @build TestUseSHA512IntrinsicsOptionOnUnsupportedCPU * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/compiler/intrinsics/sha/cli/TestUseSHAOptionOnSupportedCPU.java b/hotspot/test/compiler/intrinsics/sha/cli/TestUseSHAOptionOnSupportedCPU.java index bfc358ec939..68f48be26a8 100644 --- a/hotspot/test/compiler/intrinsics/sha/cli/TestUseSHAOptionOnSupportedCPU.java +++ b/hotspot/test/compiler/intrinsics/sha/cli/TestUseSHAOptionOnSupportedCPU.java @@ -25,7 +25,7 @@ * @test * @bug 8035968 * @summary Verify UseSHA option processing on supported CPU, - * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary testcases + * @library /testlibrary /../../test/lib /compiler/testlibrary testcases * @build TestUseSHAOptionOnSupportedCPU * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/compiler/intrinsics/sha/cli/TestUseSHAOptionOnUnsupportedCPU.java b/hotspot/test/compiler/intrinsics/sha/cli/TestUseSHAOptionOnUnsupportedCPU.java index b165c3120e7..fb666af0cbe 100644 --- a/hotspot/test/compiler/intrinsics/sha/cli/TestUseSHAOptionOnUnsupportedCPU.java +++ b/hotspot/test/compiler/intrinsics/sha/cli/TestUseSHAOptionOnUnsupportedCPU.java @@ -25,7 +25,7 @@ * @test * @bug 8035968 * @summary Verify UseSHA option processing on unsupported CPU. - * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary testcases + * @library /testlibrary /../../test/lib /compiler/testlibrary testcases * @build TestUseSHAOptionOnUnsupportedCPU * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/compiler/intrinsics/sha/cli/testcases/GenericTestCaseForOtherCPU.java b/hotspot/test/compiler/intrinsics/sha/cli/testcases/GenericTestCaseForOtherCPU.java index c5d21ed4baa..a67883166ba 100644 --- a/hotspot/test/compiler/intrinsics/sha/cli/testcases/GenericTestCaseForOtherCPU.java +++ b/hotspot/test/compiler/intrinsics/sha/cli/testcases/GenericTestCaseForOtherCPU.java @@ -41,30 +41,42 @@ public class GenericTestCaseForOtherCPU extends @Override protected void verifyWarnings() throws Throwable { + String shouldPassMessage = String.format("JVM should start with " + + "option '%s' without any warnings", optionName); // Verify that on non-x86 and non-SPARC CPU usage of SHA-related // options will not cause any warnings. CommandLineOptionTest.verifySameJVMStartup(null, - new String[] { ".*" + optionName + ".*" }, ExitCode.OK, + new String[] { ".*" + optionName + ".*" }, shouldPassMessage, + shouldPassMessage, ExitCode.OK, CommandLineOptionTest.prepareBooleanFlag(optionName, true)); CommandLineOptionTest.verifySameJVMStartup(null, - new String[] { ".*" + optionName + ".*" }, ExitCode.OK, + new String[] { ".*" + optionName + ".*" }, shouldPassMessage, + shouldPassMessage, ExitCode.OK, CommandLineOptionTest.prepareBooleanFlag(optionName, false)); } @Override protected void verifyOptionValues() throws Throwable { // Verify that option is disabled by default. - CommandLineOptionTest.verifyOptionValueForSameVM(optionName, "false"); + CommandLineOptionTest.verifyOptionValueForSameVM(optionName, "false", + String.format("Option '%s' should be disabled by default", + optionName)); // Verify that option is disabled even if it was explicitly enabled // using CLI options. CommandLineOptionTest.verifyOptionValueForSameVM(optionName, "false", + String.format("Option '%s' should be off on unsupported " + + "CPU even if set to true directly", optionName), CommandLineOptionTest.prepareBooleanFlag(optionName, true)); // Verify that option is disabled when it explicitly disabled // using CLI options. CommandLineOptionTest.verifyOptionValueForSameVM(optionName, "false", + String.format("Option '%s' should be off on unsupported CPU" + + " even if '%s' flag set to JVM", optionName, + CommandLineOptionTest.prepareBooleanFlag( + SHAOptionsBase.USE_SHA_OPTION, true)), CommandLineOptionTest.prepareBooleanFlag(optionName, false)); } } diff --git a/hotspot/test/compiler/intrinsics/sha/cli/testcases/GenericTestCaseForSupportedSparcCPU.java b/hotspot/test/compiler/intrinsics/sha/cli/testcases/GenericTestCaseForSupportedSparcCPU.java index c8ce2d52ca0..e87943d9655 100644 --- a/hotspot/test/compiler/intrinsics/sha/cli/testcases/GenericTestCaseForSupportedSparcCPU.java +++ b/hotspot/test/compiler/intrinsics/sha/cli/testcases/GenericTestCaseForSupportedSparcCPU.java @@ -39,17 +39,24 @@ public class GenericTestCaseForSupportedSparcCPU extends @Override protected void verifyWarnings() throws Throwable { + + String shouldPassMessage = String.format("JVM should start with option" + + " '%s' without any warnings", optionName); // Verify that there are no warning when option is explicitly enabled. CommandLineOptionTest.verifySameJVMStartup(null, new String[] { SHAOptionsBase.getWarningForUnsupportedCPU(optionName) - }, ExitCode.OK, + }, shouldPassMessage, shouldPassMessage, ExitCode.OK, CommandLineOptionTest.prepareBooleanFlag(optionName, true)); // Verify that option could be disabled even if +UseSHA was passed to // JVM. CommandLineOptionTest.verifySameJVMStartup(null, new String[] { SHAOptionsBase.getWarningForUnsupportedCPU(optionName) - }, ExitCode.OK, + }, shouldPassMessage, String.format("It should be able to " + + "disable option '%s' even if %s was passed to JVM", + optionName, CommandLineOptionTest.prepareBooleanFlag( + SHAOptionsBase.USE_SHA_OPTION, true)), + ExitCode.OK, CommandLineOptionTest.prepareBooleanFlag( SHAOptionsBase.USE_SHA_OPTION, true), CommandLineOptionTest.prepareBooleanFlag(optionName, false)); @@ -58,7 +65,11 @@ public class GenericTestCaseForSupportedSparcCPU extends // all SHA intrinsics via -UseSHA without any warnings. CommandLineOptionTest.verifySameJVMStartup(null, new String[] { SHAOptionsBase.getWarningForUnsupportedCPU(optionName) - }, ExitCode.OK, + }, shouldPassMessage, String.format("It should be able to " + + "enable option '%s' even if %s was passed to JVM", + optionName, CommandLineOptionTest.prepareBooleanFlag( + SHAOptionsBase.USE_SHA_OPTION, false)), + ExitCode.OK, CommandLineOptionTest.prepareBooleanFlag( SHAOptionsBase.USE_SHA_OPTION, false), CommandLineOptionTest.prepareBooleanFlag(optionName, true)); @@ -66,19 +77,30 @@ public class GenericTestCaseForSupportedSparcCPU extends @Override protected void verifyOptionValues() throws Throwable { - // Verify that on supported CPU option is enabled by default. - CommandLineOptionTest.verifyOptionValueForSameVM(optionName, "true"); + // Verify that "It should be able to disable option " + + CommandLineOptionTest.verifyOptionValueForSameVM(optionName, "true", + String.format("Option '%s' should be enabled by default", + optionName)); // Verify that it is possible to explicitly enable the option. CommandLineOptionTest.verifyOptionValueForSameVM(optionName, "true", + String.format("Option '%s' was set to have value 'true'", + optionName), CommandLineOptionTest.prepareBooleanFlag(optionName, true)); // Verify that it is possible to explicitly disable the option. CommandLineOptionTest.verifyOptionValueForSameVM(optionName, "false", + String.format("Option '%s' was set to have value 'false'", + optionName), CommandLineOptionTest.prepareBooleanFlag(optionName, false)); // verify that option is disabled when -UseSHA was passed to JVM. CommandLineOptionTest.verifyOptionValueForSameVM(optionName, "false", + String.format("Option '%s' should have value 'false' when %s" + + " flag set to JVM", optionName, + CommandLineOptionTest.prepareBooleanFlag( + SHAOptionsBase.USE_SHA_OPTION, false)), CommandLineOptionTest.prepareBooleanFlag(optionName, true), CommandLineOptionTest.prepareBooleanFlag( SHAOptionsBase.USE_SHA_OPTION, false)); @@ -86,6 +108,10 @@ public class GenericTestCaseForSupportedSparcCPU extends // Verify that it is possible to explicitly disable the tested option // even if +UseSHA was passed to JVM. CommandLineOptionTest.verifyOptionValueForSameVM(optionName, "false", + String.format("Option '%s' should have value 'false' if set so" + + " even if %s flag set to JVM", optionName, + CommandLineOptionTest.prepareBooleanFlag( + SHAOptionsBase.USE_SHA_OPTION, true)), CommandLineOptionTest.prepareBooleanFlag( SHAOptionsBase.USE_SHA_OPTION, true), CommandLineOptionTest.prepareBooleanFlag(optionName, false)); diff --git a/hotspot/test/compiler/intrinsics/sha/cli/testcases/GenericTestCaseForUnsupportedSparcCPU.java b/hotspot/test/compiler/intrinsics/sha/cli/testcases/GenericTestCaseForUnsupportedSparcCPU.java index 43bda2fb07a..e2a85fe6271 100644 --- a/hotspot/test/compiler/intrinsics/sha/cli/testcases/GenericTestCaseForUnsupportedSparcCPU.java +++ b/hotspot/test/compiler/intrinsics/sha/cli/testcases/GenericTestCaseForUnsupportedSparcCPU.java @@ -41,25 +41,35 @@ public class GenericTestCaseForUnsupportedSparcCPU extends @Override protected void verifyWarnings() throws Throwable { + String shouldPassMessage = String.format("JVM startup should pass with" + + "option '-XX:-%s' without any warnings", optionName); //Verify that option could be disabled without any warnings. CommandLineOptionTest.verifySameJVMStartup(null, new String[] { SHAOptionsBase.getWarningForUnsupportedCPU(optionName) - }, ExitCode.OK, + }, shouldPassMessage, shouldPassMessage, ExitCode.OK, CommandLineOptionTest.prepareBooleanFlag(optionName, false)); } @Override protected void verifyOptionValues() throws Throwable { // Verify that option is disabled by default. - CommandLineOptionTest.verifyOptionValueForSameVM(optionName, "false"); + CommandLineOptionTest.verifyOptionValueForSameVM(optionName, "false", + String.format("Option '%s' should be disabled by default", + optionName)); // Verify that option is disabled even if it was explicitly enabled // using CLI options. CommandLineOptionTest.verifyOptionValueForSameVM(optionName, "false", + String.format("Option '%s' should be off on unsupported " + + "SparcCPU even if set to true directly", optionName), CommandLineOptionTest.prepareBooleanFlag(optionName, true)); // Verify that option is disabled when +UseSHA was passed to JVM. CommandLineOptionTest.verifyOptionValueForSameVM(optionName, "false", + String.format("Option '%s' should be off on unsupported " + + "SparcCPU even if %s flag set to JVM", + optionName, CommandLineOptionTest.prepareBooleanFlag( + SHAOptionsBase.USE_SHA_OPTION, true)), CommandLineOptionTest.prepareBooleanFlag( SHAOptionsBase.USE_SHA_OPTION, true)); } diff --git a/hotspot/test/compiler/intrinsics/sha/cli/testcases/GenericTestCaseForUnsupportedX86CPU.java b/hotspot/test/compiler/intrinsics/sha/cli/testcases/GenericTestCaseForUnsupportedX86CPU.java index d7033e52448..5c5d3d32e64 100644 --- a/hotspot/test/compiler/intrinsics/sha/cli/testcases/GenericTestCaseForUnsupportedX86CPU.java +++ b/hotspot/test/compiler/intrinsics/sha/cli/testcases/GenericTestCaseForUnsupportedX86CPU.java @@ -38,33 +38,45 @@ public class GenericTestCaseForUnsupportedX86CPU @Override protected void verifyWarnings() throws Throwable { + String shouldPassMessage = String.format("JVM should start with '-XX:+" + + "%s' flag, but output should contain warning.", optionName); // Verify that when the tested option is explicitly enabled, then // a warning will occur in VM output. CommandLineOptionTest.verifySameJVMStartup(new String[] { SHAOptionsBase.getWarningForUnsupportedCPU(optionName) - }, null, ExitCode.OK, + }, null, shouldPassMessage, shouldPassMessage, ExitCode.OK, CommandLineOptionTest.prepareBooleanFlag(optionName, true)); + shouldPassMessage = String.format("JVM should start with '-XX:-%s' " + + "flag without any warnings", optionName); // Verify that the tested option could be explicitly disabled without // a warning. CommandLineOptionTest.verifySameJVMStartup(null, new String[] { SHAOptionsBase.getWarningForUnsupportedCPU(optionName) - }, ExitCode.OK, + }, shouldPassMessage, shouldPassMessage, ExitCode.OK, CommandLineOptionTest.prepareBooleanFlag(optionName, false)); } @Override protected void verifyOptionValues() throws Throwable { // Verify that the tested option is disabled by default. - CommandLineOptionTest.verifyOptionValueForSameVM(optionName, "false"); + CommandLineOptionTest.verifyOptionValueForSameVM(optionName, "false", + String.format("Option '%s' should be disabled by default", + optionName)); // Verify that it is not possible to explicitly enable the option. CommandLineOptionTest.verifyOptionValueForSameVM(optionName, "false", + String.format("Option '%s' should be off on unsupported " + + "X86CPU even if set to true directly", optionName), CommandLineOptionTest.prepareBooleanFlag(optionName, true)); // Verify that the tested option is disabled even if +UseSHA was passed // to JVM. CommandLineOptionTest.verifyOptionValueForSameVM(optionName, "false", + String.format("Option '%s' should be off on unsupported " + + "X86CPU even if %s flag set to JVM", + optionName, CommandLineOptionTest.prepareBooleanFlag( + SHAOptionsBase.USE_SHA_OPTION, true)), CommandLineOptionTest.prepareBooleanFlag( SHAOptionsBase.USE_SHA_OPTION, true)); } diff --git a/hotspot/test/compiler/intrinsics/sha/cli/testcases/UseSHAIntrinsicsSpecificTestCaseForUnsupportedSparcCPU.java b/hotspot/test/compiler/intrinsics/sha/cli/testcases/UseSHAIntrinsicsSpecificTestCaseForUnsupportedSparcCPU.java index 4e208eec958..16b925bafe5 100644 --- a/hotspot/test/compiler/intrinsics/sha/cli/testcases/UseSHAIntrinsicsSpecificTestCaseForUnsupportedSparcCPU.java +++ b/hotspot/test/compiler/intrinsics/sha/cli/testcases/UseSHAIntrinsicsSpecificTestCaseForUnsupportedSparcCPU.java @@ -50,10 +50,13 @@ public class UseSHAIntrinsicsSpecificTestCaseForUnsupportedSparcCPU } @Override protected void verifyWarnings() throws Throwable { - // Verify that attempt to enable the tested option will cause a warning. + String shouldPassMessage = String.format("JVM should start with " + + "'-XX:+%s' flag, but output should contain warning.", + optionName); + // Verify that attempt to enable the tested option will cause a warning CommandLineOptionTest.verifySameJVMStartup(new String[] { SHAOptionsBase.getWarningForUnsupportedCPU(optionName) - }, null, ExitCode.OK, + }, null, shouldPassMessage, shouldPassMessage, ExitCode.OK, CommandLineOptionTest.prepareBooleanFlag(optionName, true)); } } diff --git a/hotspot/test/compiler/intrinsics/sha/cli/testcases/UseSHASpecificTestCaseForSupportedSparcCPU.java b/hotspot/test/compiler/intrinsics/sha/cli/testcases/UseSHASpecificTestCaseForSupportedSparcCPU.java index f547568398a..95046ea125d 100644 --- a/hotspot/test/compiler/intrinsics/sha/cli/testcases/UseSHASpecificTestCaseForSupportedSparcCPU.java +++ b/hotspot/test/compiler/intrinsics/sha/cli/testcases/UseSHASpecificTestCaseForSupportedSparcCPU.java @@ -39,16 +39,22 @@ public class UseSHASpecificTestCaseForSupportedSparcCPU IntrinsicPredicates.ANY_SHA_INSTRUCTION_AVAILABLE)); Asserts.assertEQ(optionName, SHAOptionsBase.USE_SHA_OPTION, - "Test case should be used for " + SHAOptionsBase.USE_SHA_OPTION - + " option only."); + String.format("Test case should be used for '%s' option only.", + SHAOptionsBase.USE_SHA_OPTION)); } @Override protected void verifyWarnings() throws Throwable { + String shouldPassMessage = String.format("JVM startup should pass when" + + " %s was passed and all UseSHA*Intrinsics options " + + "were disabled", + CommandLineOptionTest.prepareBooleanFlag( + SHAOptionsBase.USE_SHA_OPTION, true)); // Verify that there will be no warnings when +UseSHA was passed and // all UseSHA*Intrinsics options were disabled. CommandLineOptionTest.verifySameJVMStartup( - null, new String[] { ".*UseSHA.*" }, ExitCode.OK, + null, new String[] { ".*UseSHA.*" }, shouldPassMessage, + shouldPassMessage, ExitCode.OK, CommandLineOptionTest.prepareBooleanFlag( SHAOptionsBase.USE_SHA_OPTION, true), CommandLineOptionTest.prepareBooleanFlag( @@ -61,10 +67,12 @@ public class UseSHASpecificTestCaseForSupportedSparcCPU @Override protected void verifyOptionValues() throws Throwable { - // Verify that UseSHA is disabled when all UseSHA*Intrinscs are + // Verify that UseSHA is disabled when all UseSHA*Intrinsics are // disabled. CommandLineOptionTest.verifyOptionValueForSameVM( - SHAOptionsBase.USE_SHA_OPTION, "false", + SHAOptionsBase.USE_SHA_OPTION, "false", String.format( + "'%s' option should be disabled when all UseSHA*Intrinsics are" + + " disabled", SHAOptionsBase.USE_SHA_OPTION), CommandLineOptionTest.prepareBooleanFlag( SHAOptionsBase.USE_SHA1_INTRINSICS_OPTION, false), CommandLineOptionTest.prepareBooleanFlag( @@ -73,9 +81,14 @@ public class UseSHASpecificTestCaseForSupportedSparcCPU SHAOptionsBase.USE_SHA512_INTRINSICS_OPTION, false)); CommandLineOptionTest.verifyOptionValueForSameVM( - // Verify that UseSHA is disabled when all UseSHA*Intrinscs are + // Verify that UseSHA is disabled when all UseSHA*Intrinsics are // disabled even if it was explicitly enabled. SHAOptionsBase.USE_SHA_OPTION, "false", + String.format("'%s' option should be disabled when all " + + "UseSHA*Intrinsics are disabled even if %s flag set " + + "to JVM", SHAOptionsBase.USE_SHA_OPTION, + CommandLineOptionTest.prepareBooleanFlag( + SHAOptionsBase.USE_SHA_OPTION, true)), CommandLineOptionTest.prepareBooleanFlag( SHAOptionsBase.USE_SHA_OPTION, true), CommandLineOptionTest.prepareBooleanFlag( @@ -89,6 +102,11 @@ public class UseSHASpecificTestCaseForSupportedSparcCPU // if all UseSHA*Intrinsics options were enabled. CommandLineOptionTest.verifyOptionValueForSameVM( SHAOptionsBase.USE_SHA_OPTION, "false", + String.format("'%s' option should be disabled if %s flag " + + "set even if all UseSHA*Intrinsics were enabled", + SHAOptionsBase.USE_SHA_OPTION, + CommandLineOptionTest.prepareBooleanFlag( + SHAOptionsBase.USE_SHA_OPTION, false)), CommandLineOptionTest.prepareBooleanFlag( SHAOptionsBase.USE_SHA_OPTION, false), CommandLineOptionTest.prepareBooleanFlag( diff --git a/hotspot/test/compiler/intrinsics/sha/cli/testcases/UseSHASpecificTestCaseForUnsupportedSparcCPU.java b/hotspot/test/compiler/intrinsics/sha/cli/testcases/UseSHASpecificTestCaseForUnsupportedSparcCPU.java index 5aceed60715..fb81f6e3d79 100644 --- a/hotspot/test/compiler/intrinsics/sha/cli/testcases/UseSHASpecificTestCaseForUnsupportedSparcCPU.java +++ b/hotspot/test/compiler/intrinsics/sha/cli/testcases/UseSHASpecificTestCaseForUnsupportedSparcCPU.java @@ -48,18 +48,24 @@ public class UseSHASpecificTestCaseForUnsupportedSparcCPU @Override protected void verifyWarnings() throws Throwable { // Verify that attempt to use UseSHA option will cause a warning. + String shouldPassMessage = String.format("JVM startup should pass with" + + " '%s' option on unsupported SparcCPU, but there should be" + + "the message shown.", optionName); CommandLineOptionTest.verifySameJVMStartup(new String[] { SHAOptionsBase.getWarningForUnsupportedCPU(optionName) - }, null, ExitCode.OK, + }, null, shouldPassMessage, shouldPassMessage, ExitCode.OK, CommandLineOptionTest.prepareBooleanFlag(optionName, true)); } @Override protected void verifyOptionValues() throws Throwable { // Verify that UseSHA option remains disabled even if all - // UseSHA*Intrincs options were enabled. + // UseSHA*Intrinsics were enabled. CommandLineOptionTest.verifyOptionValueForSameVM( - SHAOptionsBase.USE_SHA_OPTION, "false", + SHAOptionsBase.USE_SHA_OPTION, "false", String.format( + "%s option should be disabled on unsupported SparcCPU" + + " even if all UseSHA*Intrinsics options were enabled.", + SHAOptionsBase.USE_SHA_OPTION), CommandLineOptionTest.prepareBooleanFlag( SHAOptionsBase.USE_SHA1_INTRINSICS_OPTION, true), CommandLineOptionTest.prepareBooleanFlag( @@ -68,9 +74,14 @@ public class UseSHASpecificTestCaseForUnsupportedSparcCPU SHAOptionsBase.USE_SHA512_INTRINSICS_OPTION, true)); // Verify that UseSHA option remains disabled even if all - // UseSHA*Intrincs options were enabled and UseSHA was enabled as well. + // UseSHA*Intrinsics options were enabled and UseSHA was enabled as well. CommandLineOptionTest.verifyOptionValueForSameVM( - SHAOptionsBase.USE_SHA_OPTION, "false", + SHAOptionsBase.USE_SHA_OPTION, "false", String.format( + "%s option should be disabled on unsupported SparcCPU" + + " even if all UseSHA*Intrinsics options were enabled" + + " and %s was enabled as well", + SHAOptionsBase.USE_SHA_OPTION, + SHAOptionsBase.USE_SHA_OPTION), CommandLineOptionTest.prepareBooleanFlag( SHAOptionsBase.USE_SHA_OPTION, true), CommandLineOptionTest.prepareBooleanFlag( diff --git a/hotspot/test/compiler/intrinsics/sha/sanity/TestSHA1Intrinsics.java b/hotspot/test/compiler/intrinsics/sha/sanity/TestSHA1Intrinsics.java index 123fed300af..d3e60ee4bad 100644 --- a/hotspot/test/compiler/intrinsics/sha/sanity/TestSHA1Intrinsics.java +++ b/hotspot/test/compiler/intrinsics/sha/sanity/TestSHA1Intrinsics.java @@ -25,7 +25,7 @@ * @test * @bug 8035968 * @summary Verify that SHA-1 intrinsic is actually used. - * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary ../ + * @library /testlibrary /../../test/lib /compiler/testlibrary ../ * @build TestSHA intrinsics.Verifier TestSHA1Intrinsics * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/compiler/intrinsics/sha/sanity/TestSHA1MultiBlockIntrinsics.java b/hotspot/test/compiler/intrinsics/sha/sanity/TestSHA1MultiBlockIntrinsics.java index 68e573335e0..1fca2770109 100644 --- a/hotspot/test/compiler/intrinsics/sha/sanity/TestSHA1MultiBlockIntrinsics.java +++ b/hotspot/test/compiler/intrinsics/sha/sanity/TestSHA1MultiBlockIntrinsics.java @@ -27,7 +27,7 @@ import sha.predicate.IntrinsicPredicates; * @test * @bug 8035968 * @summary Verify that SHA-1 multi block intrinsic is actually used. - * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary ../ + * @library /testlibrary /../../test/lib /compiler/testlibrary ../ * @build TestSHA intrinsics.Verifier TestSHA1MultiBlockIntrinsics * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/compiler/intrinsics/sha/sanity/TestSHA256Intrinsics.java b/hotspot/test/compiler/intrinsics/sha/sanity/TestSHA256Intrinsics.java index 2730ed35a04..0bc38aeb820 100644 --- a/hotspot/test/compiler/intrinsics/sha/sanity/TestSHA256Intrinsics.java +++ b/hotspot/test/compiler/intrinsics/sha/sanity/TestSHA256Intrinsics.java @@ -27,7 +27,7 @@ import sha.predicate.IntrinsicPredicates; * @test * @bug 8035968 * @summary Verify that SHA-256 intrinsic is actually used. - * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary ../ + * @library /testlibrary /../../test/lib /compiler/testlibrary ../ * @build TestSHA intrinsics.Verifier TestSHA256Intrinsics * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/compiler/intrinsics/sha/sanity/TestSHA256MultiBlockIntrinsics.java b/hotspot/test/compiler/intrinsics/sha/sanity/TestSHA256MultiBlockIntrinsics.java index dda126dc86d..39a55078d5c 100644 --- a/hotspot/test/compiler/intrinsics/sha/sanity/TestSHA256MultiBlockIntrinsics.java +++ b/hotspot/test/compiler/intrinsics/sha/sanity/TestSHA256MultiBlockIntrinsics.java @@ -27,7 +27,7 @@ import sha.predicate.IntrinsicPredicates; * @test * @bug 8035968 * @summary Verify that SHA-256 multi block intrinsic is actually used. - * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary ../ + * @library /testlibrary /../../test/lib /compiler/testlibrary ../ * @build TestSHA intrinsics.Verifier TestSHA256MultiBlockIntrinsics * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/compiler/intrinsics/sha/sanity/TestSHA512Intrinsics.java b/hotspot/test/compiler/intrinsics/sha/sanity/TestSHA512Intrinsics.java index 02c8ad69875..e97d3a3e55d 100644 --- a/hotspot/test/compiler/intrinsics/sha/sanity/TestSHA512Intrinsics.java +++ b/hotspot/test/compiler/intrinsics/sha/sanity/TestSHA512Intrinsics.java @@ -27,7 +27,7 @@ import sha.predicate.IntrinsicPredicates; * @test * @bug 8035968 * @summary Verify that SHA-512 intrinsic is actually used. - * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary ../ + * @library /testlibrary /../../test/lib /compiler/testlibrary ../ * @build TestSHA intrinsics.Verifier TestSHA512Intrinsics * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/compiler/intrinsics/sha/sanity/TestSHA512MultiBlockIntrinsics.java b/hotspot/test/compiler/intrinsics/sha/sanity/TestSHA512MultiBlockIntrinsics.java index d958d489dba..d096d27d8e7 100644 --- a/hotspot/test/compiler/intrinsics/sha/sanity/TestSHA512MultiBlockIntrinsics.java +++ b/hotspot/test/compiler/intrinsics/sha/sanity/TestSHA512MultiBlockIntrinsics.java @@ -27,7 +27,7 @@ import sha.predicate.IntrinsicPredicates; * @test * @bug 8035968 * @summary Verify that SHA-512 multi block intrinsic is actually used. - * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary ../ + * @library /testlibrary /../../test/lib /compiler/testlibrary ../ * @build TestSHA intrinsics.Verifier TestSHA512MultiBlockIntrinsics * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/compiler/rangechecks/TestRangeCheckSmearing.java b/hotspot/test/compiler/rangechecks/TestRangeCheckSmearing.java new file mode 100644 index 00000000000..4eae3809ef8 --- /dev/null +++ b/hotspot/test/compiler/rangechecks/TestRangeCheckSmearing.java @@ -0,0 +1,436 @@ +/* + * 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 8066103 + * @summary C2's range check smearing allows out of bound array accesses + * @library /testlibrary /../../test/lib /compiler/whitebox + * @build TestRangeCheckSmearing + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main ClassFileInstaller com.oracle.java.testlibrary.Platform + * @run main/othervm -ea -Xmixed -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI + * -XX:-BackgroundCompilation -XX:-UseOnStackReplacement TestRangeCheckSmearing + * + */ + +import java.lang.annotation.*; +import java.lang.reflect.*; +import java.util.*; +import sun.hotspot.WhiteBox; +import sun.hotspot.code.NMethod; +import com.oracle.java.testlibrary.Platform; + +public class TestRangeCheckSmearing { + private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox(); + + @Retention(RetentionPolicy.RUNTIME) + @interface Args { int[] value(); } + + // first range check is i + max of all constants + @Args({0, 8}) + static int m1(int[] array, int i, boolean allaccesses) { + int res = 0; + res += array[i+9]; + if (allaccesses) { + res += array[i+8]; + res += array[i+7]; + res += array[i+6]; + res += array[i+5]; + res += array[i+4]; + res += array[i+3]; + res += array[i+2]; + res += array[i+1]; + } + return res; + } + + // first range check is i + min of all constants + @Args({0, -9}) + static int m2(int[] array, int i, boolean allaccesses) { + int res = 0; + res += array[i+1]; + if (allaccesses) { + res += array[i+2]; + res += array[i+3]; + res += array[i+4]; + res += array[i+5]; + res += array[i+6]; + res += array[i+7]; + res += array[i+8]; + res += array[i+9]; + } + return res; + } + + // first range check is not i + min/max of all constants + @Args({0, 8}) + static int m3(int[] array, int i, boolean allaccesses) { + int res = 0; + res += array[i+3]; + if (allaccesses) { + res += array[i+2]; + res += array[i+1]; + res += array[i+4]; + res += array[i+5]; + res += array[i+6]; + res += array[i+7]; + res += array[i+8]; + res += array[i+9]; + } + return res; + } + + @Args({0, -9}) + static int m4(int[] array, int i, boolean allaccesses) { + int res = 0; + res += array[i+3]; + if (allaccesses) { + res += array[i+4]; + res += array[i+1]; + res += array[i+2]; + res += array[i+5]; + res += array[i+6]; + res += array[i+7]; + res += array[i+8]; + res += array[i+9]; + } + return res; + } + + @Args({0, -3}) + static int m5(int[] array, int i, boolean allaccesses) { + int res = 0; + res += array[i+3]; + res += array[i+2]; + if (allaccesses) { + res += array[i+1]; + res += array[i+4]; + res += array[i+5]; + res += array[i+6]; + res += array[i+7]; + res += array[i+8]; + res += array[i+9]; + } + return res; + } + + @Args({0, 6}) + static int m6(int[] array, int i, boolean allaccesses) { + int res = 0; + res += array[i+3]; + res += array[i+4]; + if (allaccesses) { + res += array[i+2]; + res += array[i+1]; + res += array[i+5]; + res += array[i+6]; + res += array[i+7]; + res += array[i+8]; + res += array[i+9]; + } + return res; + } + + @Args({0, 6}) + static int m7(int[] array, int i, boolean allaccesses) { + int res = 0; + res += array[i+3]; + res += array[i+2]; + res += array[i+4]; + if (allaccesses) { + res += array[i+1]; + res += array[i+5]; + res += array[i+6]; + res += array[i+7]; + res += array[i+8]; + res += array[i+9]; + } + return res; + } + + @Args({0, -3}) + static int m8(int[] array, int i, boolean allaccesses) { + int res = 0; + res += array[i+3]; + res += array[i+4]; + res += array[i+2]; + if (allaccesses) { + res += array[i+1]; + res += array[i+5]; + res += array[i+6]; + res += array[i+7]; + res += array[i+8]; + res += array[i+9]; + } + return res; + } + + @Args({6, 15}) + static int m9(int[] array, int i, boolean allaccesses) { + int res = 0; + res += array[i+3]; + if (allaccesses) { + res += array[i-2]; + res += array[i-1]; + res += array[i-4]; + res += array[i-5]; + res += array[i-6]; + } + return res; + } + + @Args({3, 12}) + static int m10(int[] array, int i, boolean allaccesses) { + int res = 0; + res += array[i+3]; + if (allaccesses) { + res += array[i-2]; + res += array[i-1]; + res += array[i-3]; + res += array[i+4]; + res += array[i+5]; + res += array[i+6]; + } + return res; + } + + @Args({3, -3}) + static int m11(int[] array, int i, boolean allaccesses) { + int res = 0; + res += array[i+3]; + res += array[i-2]; + if (allaccesses) { + res += array[i+5]; + res += array[i+6]; + } + return res; + } + + @Args({3, 6}) + static int m12(int[] array, int i, boolean allaccesses) { + int res = 0; + res += array[i+3]; + res += array[i+6]; + if (allaccesses) { + res += array[i-2]; + res += array[i-3]; + } + return res; + } + + // check that identical range check is replaced by dominating one + // only when correct + @Args({0}) + static int m13(int[] array, int i, boolean ignore) { + int res = 0; + res += array[i+3]; + res += array[i+3]; + return res; + } + + @Args({2, 0}) + static int m14(int[] array, int i, boolean ignore) { + int res = 0; + + res += array[i]; + res += array[i-2]; + res += array[i]; // If range check below were to be removed first this cannot be considered identical to first range check + res += array[i-1]; // range check removed so i-1 array access depends on previous check + + return res; + } + + static int[] m15_dummy = new int[10]; + @Args({2, 0}) + static int m15(int[] array, int i, boolean ignore) { + int res = 0; + res += array[i]; + + // When the loop is optimized out we don't want the + // array[i-1] access which is dependent on array[i]'s + // range check to become dependent on the identical range + // check above. + + int[] array2 = m15_dummy; + int j = 0; + for (; j < 10; j++); + if (j == 10) { + array2 = array; + } + + res += array2[i-2]; + res += array2[i]; + res += array2[i-1]; // range check removed so i-1 array access depends on previous check + + return res; + } + + @Args({2, 0}) + static int m16(int[] array, int i, boolean ignore) { + int res = 0; + + res += array[i]; + res += array[i-1]; + res += array[i-1]; + res += array[i-2]; + + return res; + } + + @Args({2, 0}) + static int m17(int[] array, int i, boolean ignore) { + int res = 0; + + res += array[i]; + res += array[i-2]; + res += array[i-2]; + res += array[i+2]; + res += array[i+2]; + res += array[i-1]; + res += array[i-1]; + + return res; + } + + static public void main(String[] args) { + if (WHITE_BOX.getBooleanVMFlag("BackgroundCompilation")) { + throw new AssertionError("Background compilation enabled"); + } + new TestRangeCheckSmearing().doTests(); + } + boolean success = true; + boolean exception = false; + final int[] array = new int[10]; + final HashMap tests = new HashMap<>(); + { + final Class TEST_PARAM_TYPES[] = { int[].class, int.class, boolean.class }; + for (Method m : this.getClass().getDeclaredMethods()) { + if (m.getName().matches("m[0-9]+")) { + assert(Modifier.isStatic(m.getModifiers())) : m; + assert(m.getReturnType() == int.class) : m; + assert(Arrays.equals(m.getParameterTypes(), TEST_PARAM_TYPES)) : m; + tests.put(m.getName(), m); + } + } + } + + void invokeTest(Method m, int[] array, int index, boolean z) { + try { + m.invoke(null, array, index, z); + } catch (ReflectiveOperationException roe) { + Throwable ex = roe.getCause(); + if (ex instanceof ArrayIndexOutOfBoundsException) + throw (ArrayIndexOutOfBoundsException) ex; + throw new AssertionError(roe); + } + } + + void doTest(String name) { + Method m = tests.get(name); + tests.remove(name); + int[] args = m.getAnnotation(Args.class).value(); + int index0 = args[0], index1; + boolean exceptionRequired = true; + if (args.length == 2) { + index1 = args[1]; + } else { + // no negative test for this one + assert(args.length == 1); + assert(name.equals("m13")); + exceptionRequired = false; + index1 = index0; + } + // Get the method compiled. + if (!WHITE_BOX.isMethodCompiled(m)) { + // If not, try to compile it with C2 + if(!WHITE_BOX.enqueueMethodForCompilation(m, CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION)) { + // C2 compiler not available, try to compile with C1 + WHITE_BOX.enqueueMethodForCompilation(m, CompilerWhiteBoxTest.COMP_LEVEL_SIMPLE); + } + } + if (!WHITE_BOX.isMethodCompiled(m)) { + throw new RuntimeException(m + " not compiled"); + } + + // valid access + invokeTest(m, array, index0, true); + + if (!WHITE_BOX.isMethodCompiled(m)) { + throw new RuntimeException(m + " deoptimized on valid array access"); + } + + exception = false; + boolean test_success = true; + try { + invokeTest(m, array, index1, false); + } catch(ArrayIndexOutOfBoundsException aioob) { + exception = true; + System.out.println("ArrayIndexOutOfBoundsException thrown in "+name); + } + if (!exception) { + System.out.println("ArrayIndexOutOfBoundsException was not thrown in "+name); + } + + if (Platform.isServer()) { + if (exceptionRequired == WHITE_BOX.isMethodCompiled(m)) { + System.out.println((exceptionRequired?"Didn't deoptimized":"deoptimized") + " in "+name); + test_success = false; + } + } + + if (exception != exceptionRequired) { + System.out.println((exceptionRequired?"exception required but not thrown":"not exception required but thrown") + " in "+name); + test_success = false; + } + + if (!test_success) { + success = false; + System.out.println("TEST FAILED: "+name); + } + + } + void doTests() { + doTest("m1"); + doTest("m2"); + doTest("m3"); + doTest("m4"); + doTest("m5"); + doTest("m6"); + doTest("m7"); + doTest("m8"); + doTest("m9"); + doTest("m10"); + doTest("m11"); + doTest("m12"); + doTest("m13"); + doTest("m14"); + doTest("m15"); + doTest("m16"); + doTest("m17"); + if (!success) { + throw new RuntimeException("Some tests failed"); + } + assert(tests.isEmpty()) : tests; + } +} diff --git a/hotspot/test/compiler/rangechecks/TestRangeCheckSmearingLoopOpts.java b/hotspot/test/compiler/rangechecks/TestRangeCheckSmearingLoopOpts.java new file mode 100644 index 00000000000..699754a8e8c --- /dev/null +++ b/hotspot/test/compiler/rangechecks/TestRangeCheckSmearingLoopOpts.java @@ -0,0 +1,76 @@ +/* + * 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 8048170 + * @summary Following range check smearing, range check cannot be replaced by dominating identical test. + * @run main/othervm -XX:-BackgroundCompilation -XX:-UseOnStackReplacement TestRangeCheckSmearingLoopOpts + * + */ +public class TestRangeCheckSmearingLoopOpts { + + static int dummy; + + static int m1(int[] array, int i) { + for (;;) { + for (;;) { + if (array[i] < 0) { // range check (i+0) dominates equivalent check below + break; + } + i++; + } + + // A control flow that stops IfNode::up_one_dom() + if ((i % 2)== 0) { + if ((array[i] % 2) == 0) { + dummy = i; + } + } + + // IfNode::Ideal will rewrite some range checks if Compile::allow_range_check_smearing + if (array[i-1] == 9) { // range check (i-1) unchanged + int res = array[i-3]; // range check (i-3) unchanged + res += array[i]; // range check (i+0) unchanged + res += array[i-2]; // removed redundant range check + // the previous access might be hoisted by + // PhaseIdealLoop::split_if_with_blocks_post because + // it appears to have the same guard, but it also + // depends on the previous guards + return res; + } + i++; + } + } + + static public void main(String[] args) { + int[] array = { 0, 1, 2, -3, 4, 5, -2, 7, 8, 9, -1 }; + for (int i = 0; i < 20000; i++) { + m1(array, 0); + } + array[0] = -1; + try { + m1(array, 0); + } catch(ArrayIndexOutOfBoundsException aioobe) {} + } +} diff --git a/hotspot/test/compiler/rtm/cli/RTMGenericCommandLineOptionTest.java b/hotspot/test/compiler/rtm/cli/RTMGenericCommandLineOptionTest.java index 16177156958..5b9f50aef6b 100644 --- a/hotspot/test/compiler/rtm/cli/RTMGenericCommandLineOptionTest.java +++ b/hotspot/test/compiler/rtm/cli/RTMGenericCommandLineOptionTest.java @@ -121,7 +121,9 @@ public abstract class RTMGenericCommandLineOptionTest */ protected void runNonX86TestCases() throws Throwable { CommandLineOptionTest.verifySameJVMStartup( - new String[] { errorMessage }, null, ExitCode.FAIL, + new String[] { errorMessage }, null, + String.format("Option '%s' should be unknown on non-X86CPUs.%n" + + "JVM startup should fail", optionName), "", ExitCode.FAIL, prepareOptionValue(defaultValue)); } @@ -136,12 +138,18 @@ public abstract class RTMGenericCommandLineOptionTest protected void verifyJVMStartup() throws Throwable { String optionValue = prepareOptionValue(defaultValue); + String shouldFailMessage = String.format("VM option '%s' is " + + "experimental.%nVM startup expected to fail without " + + "-XX:+UnlockExperimentalVMOptions option", optionName); + String shouldPassMessage = String.format("VM option '%s' is " + + "experimental%nVM startup should pass with " + + "-XX:+UnlockExperimentalVMOptions option", optionName); if (isExperimental) { // verify that option is experimental CommandLineOptionTest.verifySameJVMStartup( new String[] { experimentalOptionError }, - new String[] { errorMessage }, ExitCode.FAIL, - optionValue); + new String[] { errorMessage }, shouldFailMessage, + shouldFailMessage, ExitCode.FAIL, optionValue); // verify that it could be passed if experimental options // are unlocked CommandLineOptionTest.verifySameJVMStartup(null, @@ -149,13 +157,19 @@ public abstract class RTMGenericCommandLineOptionTest experimentalOptionError, errorMessage }, + shouldPassMessage, + "JVM should start without any warnings or errors", ExitCode.OK, CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS, optionValue); } else { // verify that option could be passed CommandLineOptionTest.verifySameJVMStartup(null, - new String[]{errorMessage}, ExitCode.OK, optionValue); + new String[]{errorMessage}, + String.format("VM startup shuld pass with '%s' option", + optionName), + "JVM should start without any warnings or errors", + ExitCode.OK, optionValue); } } @@ -164,10 +178,14 @@ public abstract class RTMGenericCommandLineOptionTest if (isExperimental) { CommandLineOptionTest.verifyOptionValueForSameVM(optionName, defaultValue, + String.format("Option '%s' is expected to have '%s' " + + "default value", optionName, defaultValue), CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS); } else { CommandLineOptionTest.verifyOptionValueForSameVM(optionName, - defaultValue); + defaultValue, + String.format("Option '%s' is expected to have '%s' " + + "default value", optionName, defaultValue)); } // verify other specified option values if (optionValues == null) { @@ -178,11 +196,15 @@ public abstract class RTMGenericCommandLineOptionTest if (isExperimental) { CommandLineOptionTest.verifyOptionValueForSameVM(optionName, value, + String.format("Option '%s' is set to have '%s' value", + optionName, value), CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS, prepareOptionValue(value)); } else { CommandLineOptionTest.verifyOptionValueForSameVM(optionName, - value, prepareOptionValue(value)); + value, + String.format("Option '%s' is set to have '%s' value", + optionName, value), prepareOptionValue(value)); } } } diff --git a/hotspot/test/compiler/rtm/cli/RTMLockingAwareTest.java b/hotspot/test/compiler/rtm/cli/RTMLockingAwareTest.java index bcc75ef4fbb..baa6f6d8efc 100644 --- a/hotspot/test/compiler/rtm/cli/RTMLockingAwareTest.java +++ b/hotspot/test/compiler/rtm/cli/RTMLockingAwareTest.java @@ -131,10 +131,14 @@ public abstract class RTMLockingAwareTest } options.add(prepareOptionValue(value)); + String errorString = String.format("JVM should start with option '%s'" + + "'%nWarnings should be shown: %s", optionName, + isWarningExpected); CommandLineOptionTest.verifySameJVMStartup( (isWarningExpected ? warnings : null), (isWarningExpected ? null : warnings), - ExitCode.OK, options.toArray(new String[options.size()])); + errorString, errorString, ExitCode.OK, + options.toArray(new String[options.size()])); } private void verifyOptionValues(String value, boolean useRTMLocking, @@ -149,6 +153,9 @@ public abstract class RTMLockingAwareTest options.add(prepareOptionValue(value)); CommandLineOptionTest.verifyOptionValueForSameVM(optionName, - expectedValue, options.toArray(new String[options.size()])); + expectedValue, String.format("Option '%s' should have '%s' " + + "value if '%s' flag set", + optionName, expectedValue, prepareOptionValue(value)), + options.toArray(new String[options.size()])); } } diff --git a/hotspot/test/compiler/rtm/cli/TestPrintPreciseRTMLockingStatisticsBase.java b/hotspot/test/compiler/rtm/cli/TestPrintPreciseRTMLockingStatisticsBase.java index 2c7d56507ea..69a5fd354d5 100644 --- a/hotspot/test/compiler/rtm/cli/TestPrintPreciseRTMLockingStatisticsBase.java +++ b/hotspot/test/compiler/rtm/cli/TestPrintPreciseRTMLockingStatisticsBase.java @@ -47,27 +47,42 @@ public abstract class TestPrintPreciseRTMLockingStatisticsBase protected void verifyJVMStartup() throws Throwable { if (Platform.isServer()) { if (!Platform.isDebugBuild()) { + String shouldFailMessage = String.format("VM option '%s' is " + + "diagnostic%nJVM startup should fail without " + + "-XX:\\+UnlockDiagnosticVMOptions flag", optionName); + String shouldPassMessage = String.format("VM option '%s' is " + + "diagnostic%nJVM startup should pass with " + + "-XX:\\+UnlockDiagnosticVMOptions in debug build", + optionName); String errorMessage = CommandLineOptionTest. getDiagnosticOptionErrorMessage(optionName); // verify that option is actually diagnostic CommandLineOptionTest.verifySameJVMStartup( - new String[] { errorMessage }, null, ExitCode.FAIL, + new String[] { errorMessage }, null, shouldFailMessage, + shouldFailMessage, ExitCode.FAIL, prepareOptionValue("true")); CommandLineOptionTest.verifySameJVMStartup(null, - new String[] { errorMessage }, ExitCode.OK, + new String[] { errorMessage }, shouldPassMessage, + shouldPassMessage + "without any warnings", ExitCode.OK, CommandLineOptionTest.UNLOCK_DIAGNOSTIC_VM_OPTIONS, prepareOptionValue("true")); } else { - CommandLineOptionTest.verifySameJVMStartup( - null, null, ExitCode.OK, prepareOptionValue("true")); + String shouldPassMessage = String.format("JVM startup should " + + "pass with '%s' option in debug build", + optionName); + CommandLineOptionTest.verifySameJVMStartup(null, null, + shouldPassMessage, shouldPassMessage, + ExitCode.OK, prepareOptionValue("true")); } } else { String errorMessage = CommandLineOptionTest. getUnrecognizedOptionErrorMessage(optionName); - + String shouldFailMessage = String.format("JVM startup should fail" + + " with '%s' option in not debug build", optionName); CommandLineOptionTest.verifySameJVMStartup( - new String[]{errorMessage}, null, ExitCode.FAIL, + new String[]{errorMessage}, null, shouldFailMessage, + shouldFailMessage, ExitCode.FAIL, CommandLineOptionTest.UNLOCK_DIAGNOSTIC_VM_OPTIONS, prepareOptionValue("true")); } @@ -79,6 +94,9 @@ public abstract class TestPrintPreciseRTMLockingStatisticsBase // Verify default value CommandLineOptionTest.verifyOptionValueForSameVM(optionName, TestPrintPreciseRTMLockingStatisticsBase.DEFAULT_VALUE, + String.format("Option '%s' should have '%s' default value", + optionName, + TestPrintPreciseRTMLockingStatisticsBase.DEFAULT_VALUE), CommandLineOptionTest.UNLOCK_DIAGNOSTIC_VM_OPTIONS); } } diff --git a/hotspot/test/compiler/rtm/cli/TestPrintPreciseRTMLockingStatisticsOptionOnSupportedConfig.java b/hotspot/test/compiler/rtm/cli/TestPrintPreciseRTMLockingStatisticsOptionOnSupportedConfig.java index cb42f62141d..cf3ebabb925 100644 --- a/hotspot/test/compiler/rtm/cli/TestPrintPreciseRTMLockingStatisticsOptionOnSupportedConfig.java +++ b/hotspot/test/compiler/rtm/cli/TestPrintPreciseRTMLockingStatisticsOptionOnSupportedConfig.java @@ -27,7 +27,7 @@ * @bug 8031320 * @summary Verify PrintPreciseRTMLockingStatistics on CPUs with * rtm support and on VM with rtm locking support, - * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary + * @library /testlibrary /../../test/lib /compiler/testlibrary * @build TestPrintPreciseRTMLockingStatisticsOptionOnSupportedConfig * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission @@ -53,18 +53,28 @@ public class TestPrintPreciseRTMLockingStatisticsOptionOnSupportedConfig // verify default value CommandLineOptionTest.verifyOptionValueForSameVM(optionName, TestPrintPreciseRTMLockingStatisticsBase.DEFAULT_VALUE, + String.format("Option '%s' should have '%s' default value on" + + " supported CPU", optionName, + TestPrintPreciseRTMLockingStatisticsBase.DEFAULT_VALUE), CommandLineOptionTest.UNLOCK_DIAGNOSTIC_VM_OPTIONS, CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS, "-XX:+UseRTMLocking"); CommandLineOptionTest.verifyOptionValueForSameVM(optionName, TestPrintPreciseRTMLockingStatisticsBase.DEFAULT_VALUE, + String.format("Option '%s' should have '%s' default value on" + + " supported CPU when -XX:-UseRTMLocking flag set", + optionName, + TestPrintPreciseRTMLockingStatisticsBase.DEFAULT_VALUE), CommandLineOptionTest.UNLOCK_DIAGNOSTIC_VM_OPTIONS, CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS, "-XX:-UseRTMLocking", prepareOptionValue("true")); // verify that option could be turned on CommandLineOptionTest.verifyOptionValueForSameVM(optionName, "true", + String.format("Option '%s' should have 'true' value when set " + + "on supported CPU and -XX:+UseRTMLocking flag set", + optionName), CommandLineOptionTest.UNLOCK_DIAGNOSTIC_VM_OPTIONS, CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS, "-XX:+UseRTMLocking", prepareOptionValue("true")); diff --git a/hotspot/test/compiler/rtm/cli/TestPrintPreciseRTMLockingStatisticsOptionOnUnsupportedConfig.java b/hotspot/test/compiler/rtm/cli/TestPrintPreciseRTMLockingStatisticsOptionOnUnsupportedConfig.java index 5190bb8ec55..b3e7bbe4a2c 100644 --- a/hotspot/test/compiler/rtm/cli/TestPrintPreciseRTMLockingStatisticsOptionOnUnsupportedConfig.java +++ b/hotspot/test/compiler/rtm/cli/TestPrintPreciseRTMLockingStatisticsOptionOnUnsupportedConfig.java @@ -27,7 +27,7 @@ * @bug 8031320 * @summary Verify PrintPreciseRTMLockingStatistics on CPUs without * rtm support and/or unsupported VM. - * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary + * @library /testlibrary /../../test/lib /compiler/testlibrary * @build TestPrintPreciseRTMLockingStatisticsOptionOnUnsupportedConfig * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/compiler/rtm/cli/TestRTMAbortRatioOptionOnSupportedConfig.java b/hotspot/test/compiler/rtm/cli/TestRTMAbortRatioOptionOnSupportedConfig.java index ffa4bb45a0f..a44cf8c53de 100644 --- a/hotspot/test/compiler/rtm/cli/TestRTMAbortRatioOptionOnSupportedConfig.java +++ b/hotspot/test/compiler/rtm/cli/TestRTMAbortRatioOptionOnSupportedConfig.java @@ -27,7 +27,7 @@ * @bug 8031320 * @summary Verify RTMAbortRatio option processing on CPU with rtm * support and on VM with rtm locking support. - * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary + * @library /testlibrary /../../test/lib /compiler/testlibrary * @build TestRTMAbortRatioOptionOnSupportedConfig * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/compiler/rtm/cli/TestRTMAbortRatioOptionOnUnsupportedConfig.java b/hotspot/test/compiler/rtm/cli/TestRTMAbortRatioOptionOnUnsupportedConfig.java index eb952eebdd5..3dfd8937ea1 100644 --- a/hotspot/test/compiler/rtm/cli/TestRTMAbortRatioOptionOnUnsupportedConfig.java +++ b/hotspot/test/compiler/rtm/cli/TestRTMAbortRatioOptionOnUnsupportedConfig.java @@ -27,7 +27,7 @@ * @bug 8031320 * @summary Verify RTMAbortRatio option processing on CPU without rtm * support or on VM that does not support rtm locking. - * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary + * @library /testlibrary /../../test/lib /compiler/testlibrary * @build TestRTMAbortRatioOptionOnUnsupportedConfig * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/compiler/rtm/cli/TestRTMTotalCountIncrRateOptionOnSupportedConfig.java b/hotspot/test/compiler/rtm/cli/TestRTMTotalCountIncrRateOptionOnSupportedConfig.java index 979615d6c9e..3e982c6945c 100644 --- a/hotspot/test/compiler/rtm/cli/TestRTMTotalCountIncrRateOptionOnSupportedConfig.java +++ b/hotspot/test/compiler/rtm/cli/TestRTMTotalCountIncrRateOptionOnSupportedConfig.java @@ -27,7 +27,7 @@ * @bug 8031320 * @summary Verify RTMTotalCountIncrRate option processing on CPU with * rtm support and on VM with rtm locking support. - * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary + * @library /testlibrary /../../test/lib /compiler/testlibrary * @build TestRTMTotalCountIncrRateOptionOnSupportedConfig * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/compiler/rtm/cli/TestRTMTotalCountIncrRateOptionOnUnsupportedConfig.java b/hotspot/test/compiler/rtm/cli/TestRTMTotalCountIncrRateOptionOnUnsupportedConfig.java index 8dcffdee53e..69617d423bf 100644 --- a/hotspot/test/compiler/rtm/cli/TestRTMTotalCountIncrRateOptionOnUnsupportedConfig.java +++ b/hotspot/test/compiler/rtm/cli/TestRTMTotalCountIncrRateOptionOnUnsupportedConfig.java @@ -32,7 +32,7 @@ import rtm.predicate.SupportedVM; * @bug 8031320 * @summary Verify RTMTotalCountIncrRate option processing on CPU without * rtm support and/or on VM without rtm locking support. - * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary + * @library /testlibrary /../../test/lib /compiler/testlibrary * @build TestRTMTotalCountIncrRateOptionOnUnsupportedConfig * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/compiler/rtm/cli/TestUseRTMDeoptOptionOnSupportedConfig.java b/hotspot/test/compiler/rtm/cli/TestUseRTMDeoptOptionOnSupportedConfig.java index c921b9b3f11..de40746ec9f 100644 --- a/hotspot/test/compiler/rtm/cli/TestUseRTMDeoptOptionOnSupportedConfig.java +++ b/hotspot/test/compiler/rtm/cli/TestUseRTMDeoptOptionOnSupportedConfig.java @@ -27,7 +27,7 @@ * @bug 8031320 * @summary Verify UseRTMDeopt option processing on CPUs with rtm support * when rtm locking is supported by VM. - * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary + * @library /testlibrary /../../test/lib /compiler/testlibrary * @build TestUseRTMDeoptOptionOnSupportedConfig * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission @@ -51,26 +51,40 @@ public class TestUseRTMDeoptOptionOnSupportedConfig @Override public void runTestCases() throws Throwable { + String shouldPassMessage = " JVM should startup with option '" + + "-XX:+UseRTMDeopt' without any warnings"; // verify that option could be turned on CommandLineOptionTest.verifySameJVMStartup( - null, null, ExitCode.OK, "-XX:+UseRTMDeopt"); + null, null, shouldPassMessage, shouldPassMessage, ExitCode.OK, + "-XX:+UseRTMDeopt"); + shouldPassMessage = " JVM should startup with option '" + + "-XX:-UseRTMDeopt' without any warnings"; // verify that option could be turned off CommandLineOptionTest.verifySameJVMStartup( - null, null, ExitCode.OK, "-XX:-UseRTMDeopt"); - // verify default value - CommandLineOptionTest.verifyOptionValueForSameVM("UseRTMDeopt", - TestUseRTMDeoptOptionOnSupportedConfig.DEFAULT_VALUE); + null, null, shouldPassMessage, shouldPassMessage, ExitCode.OK, + "-XX:-UseRTMDeopt"); + String defValMessage = String.format("UseRTMDeopt should have '%s'" + + "default value", + TestUseRTMDeoptOptionOnSupportedConfig.DEFAULT_VALUE); // verify default value CommandLineOptionTest.verifyOptionValueForSameVM("UseRTMDeopt", TestUseRTMDeoptOptionOnSupportedConfig.DEFAULT_VALUE, + defValMessage); + // verify default value + CommandLineOptionTest.verifyOptionValueForSameVM("UseRTMDeopt", + TestUseRTMDeoptOptionOnSupportedConfig.DEFAULT_VALUE, + defValMessage, CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS, "-XX:+UseRTMLocking"); // verify that option is off when UseRTMLocking is off - CommandLineOptionTest.verifyOptionValueForSameVM("UseRTMDeopt", "false", + CommandLineOptionTest.verifyOptionValueForSameVM("UseRTMDeopt", + "false", "UseRTMDeopt should be off when UseRTMLocking is off", CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS, "-XX:-UseRTMLocking", "-XX:+UseRTMDeopt"); // verify that option could be turned on CommandLineOptionTest.verifyOptionValueForSameVM("UseRTMDeopt", "true", + "UseRTMDeopt should be on when UseRTMLocking is on and " + + "'-XX:+UseRTMDeopt' flag set", CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS, "-XX:+UseRTMLocking", "-XX:+UseRTMDeopt"); } diff --git a/hotspot/test/compiler/rtm/cli/TestUseRTMDeoptOptionOnUnsupportedConfig.java b/hotspot/test/compiler/rtm/cli/TestUseRTMDeoptOptionOnUnsupportedConfig.java index 6679df1297b..59f9f450feb 100644 --- a/hotspot/test/compiler/rtm/cli/TestUseRTMDeoptOptionOnUnsupportedConfig.java +++ b/hotspot/test/compiler/rtm/cli/TestUseRTMDeoptOptionOnUnsupportedConfig.java @@ -27,7 +27,7 @@ * @bug 8031320 * @summary Verify UseRTMDeopt option processing on CPUs without rtm support * or on VMs without rtm locking support. - * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary + * @library /testlibrary /../../test/lib /compiler/testlibrary * @build TestUseRTMDeoptOptionOnUnsupportedConfig * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission @@ -50,7 +50,8 @@ public class TestUseRTMDeoptOptionOnUnsupportedConfig super(new NotPredicate(new AndPredicate(new SupportedCPU(), new SupportedVM())), "UseRTMDeopt", true, false, - TestUseRTMDeoptOptionOnUnsupportedConfig.DEFAULT_VALUE, "true"); + TestUseRTMDeoptOptionOnUnsupportedConfig.DEFAULT_VALUE, + "true"); } @Override @@ -58,11 +59,16 @@ public class TestUseRTMDeoptOptionOnUnsupportedConfig super.verifyJVMStartup(); // verify default value CommandLineOptionTest.verifyOptionValueForSameVM(optionName, - defaultValue); + defaultValue, String.format("'%s' should have '%s' " + + "default value on unsupported configs.", + optionName, DEFAULT_VALUE)); // verify that until RTMLocking is not used, value // will be set to default false. CommandLineOptionTest.verifyOptionValueForSameVM(optionName, - defaultValue, "-XX:+UseRTMDeopt"); + defaultValue, String.format("'%s' should be off on unsupported" + + " configs even if '-XX:+%s' flag set", optionName, + optionName), + "-XX:+UseRTMDeopt"); } public static void main(String args[]) throws Throwable { diff --git a/hotspot/test/compiler/rtm/cli/TestUseRTMForStackLocksOptionOnSupportedConfig.java b/hotspot/test/compiler/rtm/cli/TestUseRTMForStackLocksOptionOnSupportedConfig.java index f04c154c8da..692c396354c 100644 --- a/hotspot/test/compiler/rtm/cli/TestUseRTMForStackLocksOptionOnSupportedConfig.java +++ b/hotspot/test/compiler/rtm/cli/TestUseRTMForStackLocksOptionOnSupportedConfig.java @@ -27,7 +27,7 @@ * @bug 8031320 * @summary Verify UseRTMForStackLocks option processing on CPU with * rtm support when VM supports rtm locking. - * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary + * @library /testlibrary /../../test/lib /compiler/testlibrary * @build TestUseRTMForStackLocksOptionOnSupportedConfig * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission @@ -58,43 +58,67 @@ public class TestUseRTMForStackLocksOptionOnSupportedConfig String warningMessage = RTMGenericCommandLineOptionTest.RTM_FOR_STACK_LOCKS_WARNING; + String shouldFailMessage = " VM option 'UseRTMForStackLocks' is " + + "experimental%nJVM startup should fail without " + + "-XX:+UnlockExperimentalVMOptions flag"; + CommandLineOptionTest.verifySameJVMStartup( - new String[] { errorMessage }, null, ExitCode.FAIL, + new String[] { errorMessage }, null, shouldFailMessage, + shouldFailMessage + "%nError message expected", ExitCode.FAIL, "-XX:+UseRTMForStackLocks"); + String shouldPassMessage = " VM option 'UseRTMForStackLocks'" + + " is experimental%nJVM startup should pass with " + + "-XX:+UnlockExperimentalVMOptions flag"; // verify that we get a warning when trying to use rtm for stack // lock, but not using rtm locking. CommandLineOptionTest.verifySameJVMStartup( - new String[] { warningMessage }, null, ExitCode.OK, + new String[] { warningMessage }, null, shouldPassMessage, + "There should be warning when trying to use rtm for stack " + + "lock, but not using rtm locking", ExitCode.OK, CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS, "-XX:+UseRTMForStackLocks", "-XX:-UseRTMLocking"); // verify that we don't get a warning when no using rtm for stack // lock and not using rtm locking. CommandLineOptionTest.verifySameJVMStartup(null, - new String[] { warningMessage }, ExitCode.OK, + new String[] { warningMessage }, shouldPassMessage, + "There should not be any warning when use both " + + "-XX:-UseRTMForStackLocks and -XX:-UseRTMLocking " + + "flags", + ExitCode.OK, CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS, "-XX:-UseRTMForStackLocks", "-XX:-UseRTMLocking"); // verify that we don't get a warning when using rtm for stack // lock and using rtm locking. CommandLineOptionTest.verifySameJVMStartup(null, - new String[] { warningMessage }, ExitCode.OK, + new String[] { warningMessage }, shouldPassMessage, + "There should not be any warning when use both " + + "-XX:+UseRTMForStackLocks and -XX:+UseRTMLocking" + + " flags", + ExitCode.OK, CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS, "-XX:+UseRTMForStackLocks", "-XX:+UseRTMLocking"); // verify that default value if false CommandLineOptionTest.verifyOptionValueForSameVM("UseRTMForStackLocks", TestUseRTMForStackLocksOptionOnSupportedConfig.DEFAULT_VALUE, + "Default value of option 'UseRTMForStackLocks' should be false", CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS); // verify that default value is false even with +UseRTMLocking CommandLineOptionTest.verifyOptionValueForSameVM("UseRTMForStackLocks", TestUseRTMForStackLocksOptionOnSupportedConfig.DEFAULT_VALUE, + "Default value of option 'UseRTMForStackLocks' should be false", CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS, "-XX:+UseRTMLocking"); // verify that we can turn the option on CommandLineOptionTest.verifyOptionValueForSameVM("UseRTMForStackLocks", - "true", CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS, - "-XX:+UseRTMLocking", "-XX:+UseRTMForStackLocks"); + "true", "Value of option 'UseRTMForStackLocks' should " + + "be able to be set as 'true' when both " + + "-XX:+UseRTMForStackLocks and " + + "-XX:+UseRTMLocking flags used", + CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS, + "-XX:+UseRTMLocking", "-XX:+UseRTMForStackLocks"); } public static void main(String args[]) throws Throwable { diff --git a/hotspot/test/compiler/rtm/cli/TestUseRTMForStackLocksOptionOnUnsupportedConfig.java b/hotspot/test/compiler/rtm/cli/TestUseRTMForStackLocksOptionOnUnsupportedConfig.java index bf84bde179b..829cb560368 100644 --- a/hotspot/test/compiler/rtm/cli/TestUseRTMForStackLocksOptionOnUnsupportedConfig.java +++ b/hotspot/test/compiler/rtm/cli/TestUseRTMForStackLocksOptionOnUnsupportedConfig.java @@ -27,7 +27,7 @@ * @bug 8031320 * @summary Verify UseRTMForStackLocks option processing on CPUs without * rtm support and/or on VMs without rtm locking support. - * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary + * @library /testlibrary /../../test/lib /compiler/testlibrary * @build TestUseRTMForStackLocksOptionOnUnsupportedConfig * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission @@ -57,33 +57,50 @@ public class TestUseRTMForStackLocksOptionOnUnsupportedConfig @Override protected void runX86SupportedVMTestCases() throws Throwable { + String shouldFailMessage = String.format("VM option '%s' is " + + "experimental%nJVM startup should fail without " + + "-XX:+UnlockExperimentalVMOptions flag", optionName); + // verify that option is experimental CommandLineOptionTest.verifySameJVMStartup( - new String[]{ experimentalOptionError }, - null, ExitCode.FAIL, prepareOptionValue("true")); + new String[] { experimentalOptionError }, null, + shouldFailMessage, shouldFailMessage + "%nError message " + + "should be shown", ExitCode.FAIL, + prepareOptionValue("true")); CommandLineOptionTest.verifySameJVMStartup( - new String[]{ experimentalOptionError }, - null, ExitCode.FAIL, prepareOptionValue("false")); + new String[]{ experimentalOptionError }, null, + shouldFailMessage, shouldFailMessage + "%nError message " + + "should be shown", ExitCode.FAIL, + prepareOptionValue("false")); + String shouldPassMessage = String.format("VM option '%s' is " + + " experimental%nJVM startup should pass with " + + "-XX:+UnlockExperimentalVMOptions flag", optionName); // verify that if we turn it on, then VM output will contain // warning saying that this option could be turned on only // when we use rtm locking CommandLineOptionTest.verifySameJVMStartup( new String[]{ RTMGenericCommandLineOptionTest.RTM_FOR_STACK_LOCKS_WARNING - }, - null, ExitCode.OK, + }, null, shouldPassMessage, "There should be warning when try " + + "to use rtm for stack lock, but not using rtm locking", + ExitCode.OK, CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS, prepareOptionValue("true") ); // verify that options is turned off by default CommandLineOptionTest.verifyOptionValueForSameVM(optionName, TestUseRTMForStackLocksOptionOnUnsupportedConfig.DEFAULT_VALUE, + String.format("Default value of option '%s' should be '%s'", + optionName, DEFAULT_VALUE), CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS); // verify that it could not be turned on without rtm locking CommandLineOptionTest.verifyOptionValueForSameVM(optionName, TestUseRTMForStackLocksOptionOnUnsupportedConfig.DEFAULT_VALUE, + String.format("Value of '%s' shouldn't able to be set to " + + "'true' without setting -XX:+UseRTMLocking flag", + optionName), CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS, prepareOptionValue("true")); } diff --git a/hotspot/test/compiler/rtm/cli/TestUseRTMLockingOptionOnSupportedConfig.java b/hotspot/test/compiler/rtm/cli/TestUseRTMLockingOptionOnSupportedConfig.java index cb3a777f9f7..6012d56c11c 100644 --- a/hotspot/test/compiler/rtm/cli/TestUseRTMLockingOptionOnSupportedConfig.java +++ b/hotspot/test/compiler/rtm/cli/TestUseRTMLockingOptionOnSupportedConfig.java @@ -27,7 +27,7 @@ * @bug 8031320 * @summary Verify UseRTMLocking option processing on CPU with rtm support and * on VM with rtm-locking support. - * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary + * @library /testlibrary /../../test/lib /compiler/testlibrary * @build TestUseRTMLockingOptionOnSupportedConfig * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission @@ -54,12 +54,16 @@ public class TestUseRTMLockingOptionOnSupportedConfig String unrecongnizedOption = CommandLineOptionTest.getUnrecognizedOptionErrorMessage( "UseRTMLocking"); + String shouldPassMessage = "VM option 'UseRTMLocking' is experimental" + + "%nJVM startup should pass with " + + "-XX:+UnlockExperimentalVMOptions flag"; // verify that there are no warning or error in VM output CommandLineOptionTest.verifySameJVMStartup(null, new String[]{ RTMGenericCommandLineOptionTest.RTM_INSTR_ERROR, unrecongnizedOption - }, ExitCode.OK, + }, shouldPassMessage, "There should not be any warning when use" + + "with -XX:+UnlockExperimentalVMOptions", ExitCode.OK, CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS, "-XX:+UseRTMLocking" ); @@ -68,21 +72,28 @@ public class TestUseRTMLockingOptionOnSupportedConfig new String[]{ RTMGenericCommandLineOptionTest.RTM_INSTR_ERROR, unrecongnizedOption - }, ExitCode.OK, + }, shouldPassMessage, "There should not be any warning when use" + + "with -XX:+UnlockExperimentalVMOptions", ExitCode.OK, CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS, "-XX:-UseRTMLocking" ); // verify that UseRTMLocking is of by default CommandLineOptionTest.verifyOptionValueForSameVM("UseRTMLocking", TestUseRTMLockingOptionOnSupportedConfig.DEFAULT_VALUE, + String.format("Default value of option 'UseRTMLocking' should " + + "be '%s'", DEFAULT_VALUE), CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS); // verify that we can change UseRTMLocking value CommandLineOptionTest.verifyOptionValueForSameVM("UseRTMLocking", TestUseRTMLockingOptionOnSupportedConfig.DEFAULT_VALUE, + String.format("Default value of option 'UseRTMLocking' should " + + "be '%s'", DEFAULT_VALUE), CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS, "-XX:-UseRTMLocking"); CommandLineOptionTest.verifyOptionValueForSameVM("UseRTMLocking", - "true", CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS, + "true", "Value of 'UseRTMLocking' should be set " + + "to 'true' if -XX:+UseRTMLocking flag set", + CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS, "-XX:+UseRTMLocking"); } diff --git a/hotspot/test/compiler/rtm/cli/TestUseRTMLockingOptionOnUnsupportedCPU.java b/hotspot/test/compiler/rtm/cli/TestUseRTMLockingOptionOnUnsupportedCPU.java index a4fe7d07930..3fba16e1e09 100644 --- a/hotspot/test/compiler/rtm/cli/TestUseRTMLockingOptionOnUnsupportedCPU.java +++ b/hotspot/test/compiler/rtm/cli/TestUseRTMLockingOptionOnUnsupportedCPU.java @@ -27,7 +27,7 @@ * @bug 8031320 * @summary Verify UseRTMLocking option processing on CPU without * rtm support. - * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary + * @library /testlibrary /../../test/lib /compiler/testlibrary * @build TestUseRTMLockingOptionOnUnsupportedCPU * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission @@ -59,33 +59,44 @@ public class TestUseRTMLockingOptionOnUnsupportedCPU String errorMessage = RTMGenericCommandLineOptionTest.RTM_INSTR_ERROR; if (Platform.isX86() || Platform.isX64()) { + String shouldFailMessage = "JVM startup should fail with option " + + "-XX:+UseRTMLocking on unsupported CPU"; // verify that we get an error when use +UseRTMLocking // on unsupported CPU CommandLineOptionTest.verifySameJVMStartup( new String[] { errorMessage }, - new String[] { unrecongnizedOption }, + new String[] { unrecongnizedOption }, shouldFailMessage, + shouldFailMessage + ". Error message should be shown", ExitCode.FAIL, "-XX:+UseRTMLocking"); + + String shouldPassMessage = "JVM startup should pass with option " + + "-XX:-UseRTMLocking even on unsupported CPU"; // verify that we can pass -UseRTMLocking without // getting any error messages - CommandLineOptionTest.verifySameJVMStartup( - null, - new String[]{ - errorMessage, - unrecongnizedOption - }, ExitCode.OK, "-XX:-UseRTMLocking"); + CommandLineOptionTest.verifySameJVMStartup(null, new String[] { + errorMessage, unrecongnizedOption }, shouldPassMessage, + shouldPassMessage + " without any warnings", ExitCode.OK, + "-XX:-UseRTMLocking"); // verify that UseRTMLocking is false by default CommandLineOptionTest.verifyOptionValueForSameVM("UseRTMLocking", - TestUseRTMLockingOptionOnUnsupportedCPU.DEFAULT_VALUE); + TestUseRTMLockingOptionOnUnsupportedCPU.DEFAULT_VALUE, + String.format("Default value of option 'UseRTMLocking' " + +"should be '%s'", DEFAULT_VALUE)); } else { + String shouldFailMessage = "RTMLocking should be unrecognized" + + " on non-x86 CPUs. JVM startup should fail." + + "Error message should be shown"; // verify that on non-x86 CPUs RTMLocking could not be used CommandLineOptionTest.verifySameJVMStartup( new String[] { unrecongnizedOption }, - null, ExitCode.FAIL, "-XX:+UseRTMLocking"); + null, shouldFailMessage, shouldFailMessage, + ExitCode.FAIL, "-XX:+UseRTMLocking"); CommandLineOptionTest.verifySameJVMStartup( new String[] { unrecongnizedOption }, - null, ExitCode.FAIL, "-XX:-UseRTMLocking"); + null, shouldFailMessage, shouldFailMessage, + ExitCode.FAIL, "-XX:-UseRTMLocking"); } } diff --git a/hotspot/test/compiler/rtm/cli/TestUseRTMLockingOptionOnUnsupportedVM.java b/hotspot/test/compiler/rtm/cli/TestUseRTMLockingOptionOnUnsupportedVM.java index 8119019ae56..a03122491d1 100644 --- a/hotspot/test/compiler/rtm/cli/TestUseRTMLockingOptionOnUnsupportedVM.java +++ b/hotspot/test/compiler/rtm/cli/TestUseRTMLockingOptionOnUnsupportedVM.java @@ -27,7 +27,7 @@ * @bug 8031320 * @summary Verify UseRTMLocking option processing on CPU with rtm support * in case when VM should not support this option. - * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary + * @library /testlibrary /../../test/lib /compiler/testlibrary * @build TestUseRTMLockingOptionOnUnsupportedVM * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission @@ -54,17 +54,26 @@ public class TestUseRTMLockingOptionOnUnsupportedVM public void runTestCases() throws Throwable { String errorMessage = RTMGenericCommandLineOptionTest.RTM_UNSUPPORTED_VM_ERROR; + String shouldFailMessage = "JVM startup should fail with option " + + "-XX:+UseRTMLocking even on unsupported VM. Error message" + + " should be shown"; + String shouldPassMessage = "JVM startup should pass with option " + + "-XX:-UseRTMLocking even on unsupported VM"; // verify that we can't use +UseRTMLocking CommandLineOptionTest.verifySameJVMStartup( - new String[] { errorMessage }, null, ExitCode.FAIL, - "-XX:+UseRTMLocking"); + new String[] { errorMessage }, null, shouldFailMessage, + shouldFailMessage, ExitCode.FAIL, + "-XX:+UseRTMLocking"); // verify that we can turn it off CommandLineOptionTest.verifySameJVMStartup(null, - new String[] { errorMessage }, ExitCode.OK, + new String[] { errorMessage }, shouldPassMessage, + shouldPassMessage + " without any warnings", ExitCode.OK, "-XX:-UseRTMLocking"); // verify that it is off by default CommandLineOptionTest.verifyOptionValueForSameVM("UseRTMLocking", - TestUseRTMLockingOptionOnUnsupportedVM.DEFAULT_VALUE); + TestUseRTMLockingOptionOnUnsupportedVM.DEFAULT_VALUE, + String.format("Default value of option 'UseRTMLocking' should" + + " be '%s'", DEFAULT_VALUE)); } public static void main(String args[]) throws Throwable { diff --git a/hotspot/test/compiler/rtm/cli/TestUseRTMLockingOptionWithBiasedLocking.java b/hotspot/test/compiler/rtm/cli/TestUseRTMLockingOptionWithBiasedLocking.java index 0786a608550..ed82aec36c4 100644 --- a/hotspot/test/compiler/rtm/cli/TestUseRTMLockingOptionWithBiasedLocking.java +++ b/hotspot/test/compiler/rtm/cli/TestUseRTMLockingOptionWithBiasedLocking.java @@ -27,7 +27,7 @@ * @bug 8031320 * @summary Verify processing of UseRTMLocking and UseBiasedLocking * options combination on CPU and VM with rtm support. - * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary + * @library /testlibrary /../../test/lib /compiler/testlibrary * @build TestUseRTMLockingOptionWithBiasedLocking * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission @@ -51,25 +51,44 @@ public class TestUseRTMLockingOptionWithBiasedLocking public void runTestCases() throws Throwable { String warningMessage = RTMGenericCommandLineOptionTest.RTM_BIASED_LOCKING_WARNING; + String shouldPassMessage = "JVM startup should pass with both " + + "-XX:+UseRTMLocking and " + + "-XX:-UseBiasedLocking flags set without any warnings"; // verify that we will not get a warning CommandLineOptionTest.verifySameJVMStartup(null, - new String[] { warningMessage }, ExitCode.OK, + new String[] { warningMessage }, shouldPassMessage, + shouldPassMessage, ExitCode.OK, CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS, "-XX:+UseRTMLocking", "-XX:-UseBiasedLocking"); + // verify that we will get a warning CommandLineOptionTest.verifySameJVMStartup( - new String[] { warningMessage }, null, ExitCode.OK, + new String[] { warningMessage }, null, + "JVM startup should pass when both -XX:+UseRTMLocking and " + + "-XX:+UseBiasedLocking flags set", + "Flags -XX:+UseRTMLocking" + + " and -XX:+UseBiasedLocking conflicts. " + + "Warning should be shown.", ExitCode.OK, CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS, "-XX:+UseRTMLocking", "-XX:+UseBiasedLocking"); // verify that UseBiasedLocking is false when we use rtm locking CommandLineOptionTest.verifyOptionValueForSameVM("UseBiasedLocking", - "false", CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS, + "false", + "Value of option 'UseBiasedLocking' should be false if" + + "-XX:+UseRTMLocking flag set.", + CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS, "-XX:+UseRTMLocking"); // verify that we can't turn on biased locking when // using rtm locking - CommandLineOptionTest.verifyOptionValueForSameVM("UseBiasedLocking", - "false", CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS, - "-XX:+UseRTMLocking", "-XX:+UseBiasedLocking"); + CommandLineOptionTest + .verifyOptionValueForSameVM( + "UseBiasedLocking", + "false", + "Value of option 'UseBiasedLocking' should be false if" + + "both -XX:+UseRTMLocking and " + + "-XX:+UseBiasedLocking flags set.", + CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS, + "-XX:+UseRTMLocking", "-XX:+UseBiasedLocking"); } public static void main(String args[]) throws Throwable { diff --git a/hotspot/test/compiler/rtm/locking/TestRTMAbortRatio.java b/hotspot/test/compiler/rtm/locking/TestRTMAbortRatio.java index f4eb6a9c458..02392f8db02 100644 --- a/hotspot/test/compiler/rtm/locking/TestRTMAbortRatio.java +++ b/hotspot/test/compiler/rtm/locking/TestRTMAbortRatio.java @@ -27,7 +27,7 @@ * @bug 8031320 * @summary Verify that RTMAbortRatio affects amount of aborts before * deoptimization. - * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary + * @library /testlibrary /../../test/lib /compiler/testlibrary * @build TestRTMAbortRatio * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/compiler/rtm/locking/TestRTMAbortThreshold.java b/hotspot/test/compiler/rtm/locking/TestRTMAbortThreshold.java index 9447b88c41d..7bf1548a991 100644 --- a/hotspot/test/compiler/rtm/locking/TestRTMAbortThreshold.java +++ b/hotspot/test/compiler/rtm/locking/TestRTMAbortThreshold.java @@ -27,7 +27,7 @@ * @bug 8031320 * @summary Verify that RTMAbortThreshold option affects * amount of aborts after which abort ratio is calculated. - * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary + * @library /testlibrary /../../test/lib /compiler/testlibrary * @build TestRTMAbortThreshold * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/compiler/rtm/locking/TestRTMAfterNonRTMDeopt.java b/hotspot/test/compiler/rtm/locking/TestRTMAfterNonRTMDeopt.java index d46433da725..12c659ef2d6 100644 --- a/hotspot/test/compiler/rtm/locking/TestRTMAfterNonRTMDeopt.java +++ b/hotspot/test/compiler/rtm/locking/TestRTMAfterNonRTMDeopt.java @@ -29,7 +29,7 @@ * caused by reason other then rtm_state_change will reset * method's RTM state. And if we don't use RTMDeopt, then * RTM state remain the same after such deoptimization. - * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary + * @library /testlibrary /../../test/lib /compiler/testlibrary * @build TestRTMAfterNonRTMDeopt * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/compiler/rtm/locking/TestRTMDeoptOnHighAbortRatio.java b/hotspot/test/compiler/rtm/locking/TestRTMDeoptOnHighAbortRatio.java index 4c662e088ec..0362bc97b77 100644 --- a/hotspot/test/compiler/rtm/locking/TestRTMDeoptOnHighAbortRatio.java +++ b/hotspot/test/compiler/rtm/locking/TestRTMDeoptOnHighAbortRatio.java @@ -27,7 +27,7 @@ * @bug 8031320 * @summary Verify that on high abort ratio method will be recompiled * without rtm locking. - * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary + * @library /testlibrary /../../test/lib /compiler/testlibrary * @build TestRTMDeoptOnHighAbortRatio * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/compiler/rtm/locking/TestRTMDeoptOnLowAbortRatio.java b/hotspot/test/compiler/rtm/locking/TestRTMDeoptOnLowAbortRatio.java index 4101cbf4a52..343ecc0cd83 100644 --- a/hotspot/test/compiler/rtm/locking/TestRTMDeoptOnLowAbortRatio.java +++ b/hotspot/test/compiler/rtm/locking/TestRTMDeoptOnLowAbortRatio.java @@ -26,7 +26,7 @@ * @test * @bug 8031320 * @summary Verify that on low abort ratio method will be recompiled. - * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary + * @library /testlibrary /../../test/lib /compiler/testlibrary * @build TestRTMDeoptOnLowAbortRatio * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/compiler/rtm/locking/TestRTMLockingCalculationDelay.java b/hotspot/test/compiler/rtm/locking/TestRTMLockingCalculationDelay.java index 6355d97e487..61544942bd6 100644 --- a/hotspot/test/compiler/rtm/locking/TestRTMLockingCalculationDelay.java +++ b/hotspot/test/compiler/rtm/locking/TestRTMLockingCalculationDelay.java @@ -27,7 +27,7 @@ * @bug 8031320 * @summary Verify that RTMLockingCalculationDelay affect when * abort ratio calculation is started. - * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary + * @library /testlibrary /../../test/lib /compiler/testlibrary * @build TestRTMLockingCalculationDelay * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/compiler/rtm/locking/TestRTMLockingThreshold.java b/hotspot/test/compiler/rtm/locking/TestRTMLockingThreshold.java index a30ee9a061f..c57065f5be0 100644 --- a/hotspot/test/compiler/rtm/locking/TestRTMLockingThreshold.java +++ b/hotspot/test/compiler/rtm/locking/TestRTMLockingThreshold.java @@ -27,7 +27,7 @@ * @bug 8031320 * @summary Verify that RTMLockingThreshold affects rtm state transition * ProfileRTM => UseRTM. - * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary + * @library /testlibrary /../../test/lib /compiler/testlibrary * @build TestRTMLockingThreshold * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/compiler/rtm/locking/TestRTMRetryCount.java b/hotspot/test/compiler/rtm/locking/TestRTMRetryCount.java index 4fceef23919..2c22c417f9f 100644 --- a/hotspot/test/compiler/rtm/locking/TestRTMRetryCount.java +++ b/hotspot/test/compiler/rtm/locking/TestRTMRetryCount.java @@ -26,7 +26,7 @@ * @test * @bug 8031320 * @summary Verify that RTMRetryCount affects actual amount of retries. - * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary + * @library /testlibrary /../../test/lib /compiler/testlibrary * @build TestRTMRetryCount * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/compiler/rtm/locking/TestRTMSpinLoopCount.java b/hotspot/test/compiler/rtm/locking/TestRTMSpinLoopCount.java index 1d78747bb97..121f5d36092 100644 --- a/hotspot/test/compiler/rtm/locking/TestRTMSpinLoopCount.java +++ b/hotspot/test/compiler/rtm/locking/TestRTMSpinLoopCount.java @@ -27,7 +27,7 @@ * @bug 8031320 * @summary Verify that RTMSpinLoopCount affects time spent * between locking attempts. - * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary + * @library /testlibrary /../../test/lib /compiler/testlibrary * @build TestRTMSpinLoopCount * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/compiler/rtm/locking/TestRTMTotalCountIncrRate.java b/hotspot/test/compiler/rtm/locking/TestRTMTotalCountIncrRate.java index 4af5a59c5b7..8201cb9e1a5 100644 --- a/hotspot/test/compiler/rtm/locking/TestRTMTotalCountIncrRate.java +++ b/hotspot/test/compiler/rtm/locking/TestRTMTotalCountIncrRate.java @@ -27,7 +27,7 @@ * @bug 8031320 * @summary Verify that RTMTotalCountIncrRate option affects * RTM locking statistics. - * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary + * @library /testlibrary /../../test/lib /compiler/testlibrary * @build TestRTMTotalCountIncrRate * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/compiler/rtm/locking/TestUseRTMAfterLockInflation.java b/hotspot/test/compiler/rtm/locking/TestUseRTMAfterLockInflation.java index d6ee5b6e3ba..ff7e98122b9 100644 --- a/hotspot/test/compiler/rtm/locking/TestUseRTMAfterLockInflation.java +++ b/hotspot/test/compiler/rtm/locking/TestUseRTMAfterLockInflation.java @@ -27,7 +27,7 @@ * @bug 8031320 * @summary Verify that rtm locking is used for stack locks before * inflation and after it used for inflated locks. - * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary + * @library /testlibrary /../../test/lib /compiler/testlibrary * @build TestUseRTMAfterLockInflation * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/compiler/rtm/locking/TestUseRTMDeopt.java b/hotspot/test/compiler/rtm/locking/TestUseRTMDeopt.java index 9b93ad75f09..008e502e508 100644 --- a/hotspot/test/compiler/rtm/locking/TestUseRTMDeopt.java +++ b/hotspot/test/compiler/rtm/locking/TestUseRTMDeopt.java @@ -27,7 +27,7 @@ * @bug 8031320 * @summary Verify that UseRTMDeopt affects uncommon trap installation in * copmpiled methods with synchronized block. - * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary + * @library /testlibrary /../../test/lib /compiler/testlibrary * @build TestUseRTMDeopt * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/compiler/rtm/locking/TestUseRTMForInflatedLocks.java b/hotspot/test/compiler/rtm/locking/TestUseRTMForInflatedLocks.java index 936abf8005c..1555939e7d8 100644 --- a/hotspot/test/compiler/rtm/locking/TestUseRTMForInflatedLocks.java +++ b/hotspot/test/compiler/rtm/locking/TestUseRTMForInflatedLocks.java @@ -26,7 +26,7 @@ * @test * @bug 8031320 * @summary Verify that rtm locking is used for inflated locks. - * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary + * @library /testlibrary /../../test/lib /compiler/testlibrary * @build TestUseRTMForInflatedLocks * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/compiler/rtm/locking/TestUseRTMForStackLocks.java b/hotspot/test/compiler/rtm/locking/TestUseRTMForStackLocks.java index b3b44984df0..4c89320ad83 100644 --- a/hotspot/test/compiler/rtm/locking/TestUseRTMForStackLocks.java +++ b/hotspot/test/compiler/rtm/locking/TestUseRTMForStackLocks.java @@ -26,7 +26,7 @@ * @test * @bug 8031320 * @summary Verify that rtm locking is used for stack locks. - * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary + * @library /testlibrary /../../test/lib /compiler/testlibrary * @build TestUseRTMForStackLocks * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/compiler/rtm/locking/TestUseRTMXendForLockBusy.java b/hotspot/test/compiler/rtm/locking/TestUseRTMXendForLockBusy.java index 899f96d39cf..f703dc8cc3f 100644 --- a/hotspot/test/compiler/rtm/locking/TestUseRTMXendForLockBusy.java +++ b/hotspot/test/compiler/rtm/locking/TestUseRTMXendForLockBusy.java @@ -27,7 +27,7 @@ * @bug 8031320 * @summary Verify that UseRTMXendForLockBusy option affects * method behaviour if lock is busy. - * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary + * @library /testlibrary /../../test/lib /compiler/testlibrary * @build TestUseRTMXendForLockBusy * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/compiler/rtm/method_options/TestNoRTMLockElidingOption.java b/hotspot/test/compiler/rtm/method_options/TestNoRTMLockElidingOption.java index 265f9e86c1d..dc308b5172b 100644 --- a/hotspot/test/compiler/rtm/method_options/TestNoRTMLockElidingOption.java +++ b/hotspot/test/compiler/rtm/method_options/TestNoRTMLockElidingOption.java @@ -27,7 +27,7 @@ * @bug 8031320 * @summary Verify that NoRTMLockEliding option could be applied to * specified method and that such method will not use rtm. - * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary + * @library /testlibrary /../../test/lib /compiler/testlibrary * @build TestNoRTMLockElidingOption * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/compiler/rtm/method_options/TestUseRTMLockElidingOption.java b/hotspot/test/compiler/rtm/method_options/TestUseRTMLockElidingOption.java index e2ded9c51d7..e2376ba181d 100644 --- a/hotspot/test/compiler/rtm/method_options/TestUseRTMLockElidingOption.java +++ b/hotspot/test/compiler/rtm/method_options/TestUseRTMLockElidingOption.java @@ -28,7 +28,7 @@ * @summary Verify that UseRTMLockEliding option could be applied to * specified method and that such method will not be deoptimized * on high abort ratio. - * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary + * @library /testlibrary /../../test/lib /compiler/testlibrary * @build TestUseRTMLockElidingOption * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/compiler/rtm/print/TestPrintPreciseRTMLockingStatistics.java b/hotspot/test/compiler/rtm/print/TestPrintPreciseRTMLockingStatistics.java index 39dbd2522cf..80b412272b0 100644 --- a/hotspot/test/compiler/rtm/print/TestPrintPreciseRTMLockingStatistics.java +++ b/hotspot/test/compiler/rtm/print/TestPrintPreciseRTMLockingStatistics.java @@ -29,7 +29,7 @@ * on overall aborts and locks count and count of aborts of * different types. Test also verify that VM output does not * contain rtm locking statistics when it should not. - * @library /testlibrary /testlibrary/whitebox /compiler/testlibrary + * @library /testlibrary /../../test/lib /compiler/testlibrary * @build TestPrintPreciseRTMLockingStatistics * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/compiler/runtime/8010927/Test8010927.java b/hotspot/test/compiler/runtime/8010927/Test8010927.java index 6ffbdb522a6..bb52c4c5817 100644 --- a/hotspot/test/compiler/runtime/8010927/Test8010927.java +++ b/hotspot/test/compiler/runtime/8010927/Test8010927.java @@ -25,7 +25,7 @@ * @test * @bug 8010927 * @summary Kitchensink crashed with SIGSEGV, Problematic frame: v ~StubRoutines::checkcast_arraycopy - * @library /testlibrary/whitebox /testlibrary + * @library /../../test/lib /testlibrary * @build Test8010927 * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/compiler/stable/TestStableBoolean.java b/hotspot/test/compiler/stable/TestStableBoolean.java index dfcf1edffe1..9a01ec74238 100644 --- a/hotspot/test/compiler/stable/TestStableBoolean.java +++ b/hotspot/test/compiler/stable/TestStableBoolean.java @@ -26,7 +26,7 @@ /* * @test TestStableBoolean * @summary tests on stable fields and arrays - * @library /testlibrary /testlibrary/whitebox + * @library /testlibrary /../../test/lib * @build TestStableBoolean StableConfiguration sun.hotspot.WhiteBox * @run main ClassFileInstaller sun.hotspot.WhiteBox sun.hotspot.WhiteBox$WhiteBoxPermission * @run main ClassFileInstaller diff --git a/hotspot/test/compiler/stable/TestStableByte.java b/hotspot/test/compiler/stable/TestStableByte.java index 3b2f5969bb1..de49894d06f 100644 --- a/hotspot/test/compiler/stable/TestStableByte.java +++ b/hotspot/test/compiler/stable/TestStableByte.java @@ -26,7 +26,7 @@ /* * @test TestStableByte * @summary tests on stable fields and arrays - * @library /testlibrary /testlibrary/whitebox + * @library /testlibrary /../../test/lib * @build TestStableByte StableConfiguration sun.hotspot.WhiteBox * @run main ClassFileInstaller sun.hotspot.WhiteBox sun.hotspot.WhiteBox$WhiteBoxPermission * @run main ClassFileInstaller diff --git a/hotspot/test/compiler/stable/TestStableChar.java b/hotspot/test/compiler/stable/TestStableChar.java index 84deb646168..fa5a642e1f1 100644 --- a/hotspot/test/compiler/stable/TestStableChar.java +++ b/hotspot/test/compiler/stable/TestStableChar.java @@ -26,7 +26,7 @@ /* * @test TestStableChar * @summary tests on stable fields and arrays - * @library /testlibrary /testlibrary/whitebox + * @library /testlibrary /../../test/lib * @build TestStableChar StableConfiguration sun.hotspot.WhiteBox * @run main ClassFileInstaller sun.hotspot.WhiteBox sun.hotspot.WhiteBox$WhiteBoxPermission * @run main ClassFileInstaller diff --git a/hotspot/test/compiler/stable/TestStableDouble.java b/hotspot/test/compiler/stable/TestStableDouble.java index f2f85ce4f13..98a7128ea07 100644 --- a/hotspot/test/compiler/stable/TestStableDouble.java +++ b/hotspot/test/compiler/stable/TestStableDouble.java @@ -26,7 +26,7 @@ /* * @test TestStableDouble * @summary tests on stable fields and arrays - * @library /testlibrary /testlibrary/whitebox + * @library /testlibrary /../../test/lib * @build TestStableDouble StableConfiguration sun.hotspot.WhiteBox * @run main ClassFileInstaller sun.hotspot.WhiteBox sun.hotspot.WhiteBox$WhiteBoxPermission * @run main ClassFileInstaller diff --git a/hotspot/test/compiler/stable/TestStableFloat.java b/hotspot/test/compiler/stable/TestStableFloat.java index 40e46bd6a86..13ad90ced19 100644 --- a/hotspot/test/compiler/stable/TestStableFloat.java +++ b/hotspot/test/compiler/stable/TestStableFloat.java @@ -26,7 +26,7 @@ /* * @test TestStableFloat * @summary tests on stable fields and arrays - * @library /testlibrary /testlibrary/whitebox + * @library /testlibrary /../../test/lib * @build TestStableFloat StableConfiguration sun.hotspot.WhiteBox * @run main ClassFileInstaller sun.hotspot.WhiteBox sun.hotspot.WhiteBox$WhiteBoxPermission * @run main ClassFileInstaller diff --git a/hotspot/test/compiler/stable/TestStableInt.java b/hotspot/test/compiler/stable/TestStableInt.java index beeb3808f52..55ab13da1c7 100644 --- a/hotspot/test/compiler/stable/TestStableInt.java +++ b/hotspot/test/compiler/stable/TestStableInt.java @@ -26,7 +26,7 @@ /* * @test TestStableInt * @summary tests on stable fields and arrays - * @library /testlibrary /testlibrary/whitebox + * @library /testlibrary /../../test/lib * @build TestStableInt StableConfiguration sun.hotspot.WhiteBox * @run main ClassFileInstaller sun.hotspot.WhiteBox sun.hotspot.WhiteBox$WhiteBoxPermission * @run main ClassFileInstaller diff --git a/hotspot/test/compiler/stable/TestStableLong.java b/hotspot/test/compiler/stable/TestStableLong.java index 69c90fc29d9..4b6c574f33b 100644 --- a/hotspot/test/compiler/stable/TestStableLong.java +++ b/hotspot/test/compiler/stable/TestStableLong.java @@ -26,7 +26,7 @@ /* * @test TestStableLong * @summary tests on stable fields and arrays - * @library /testlibrary /testlibrary/whitebox + * @library /testlibrary /../../test/lib * @build TestStableLong StableConfiguration sun.hotspot.WhiteBox * @run main ClassFileInstaller sun.hotspot.WhiteBox sun.hotspot.WhiteBox$WhiteBoxPermission * @run main ClassFileInstaller diff --git a/hotspot/test/compiler/stable/TestStableObject.java b/hotspot/test/compiler/stable/TestStableObject.java index 7b2f31e14f4..19fef93ce28 100644 --- a/hotspot/test/compiler/stable/TestStableObject.java +++ b/hotspot/test/compiler/stable/TestStableObject.java @@ -26,7 +26,7 @@ /* * @test TestStableObject * @summary tests on stable fields and arrays - * @library /testlibrary /testlibrary/whitebox + * @library /testlibrary /../../test/lib * @build TestStableObject StableConfiguration sun.hotspot.WhiteBox * @run main ClassFileInstaller sun.hotspot.WhiteBox sun.hotspot.WhiteBox$WhiteBoxPermission * @run main ClassFileInstaller diff --git a/hotspot/test/compiler/stable/TestStableShort.java b/hotspot/test/compiler/stable/TestStableShort.java index 52cf6477e80..20b65cfda3c 100644 --- a/hotspot/test/compiler/stable/TestStableShort.java +++ b/hotspot/test/compiler/stable/TestStableShort.java @@ -26,7 +26,7 @@ /* * @test TestStableShort * @summary tests on stable fields and arrays - * @library /testlibrary /testlibrary/whitebox + * @library /testlibrary /../../test/lib * @build TestStableShort StableConfiguration sun.hotspot.WhiteBox * @run main ClassFileInstaller sun.hotspot.WhiteBox sun.hotspot.WhiteBox$WhiteBoxPermission * @run main ClassFileInstaller diff --git a/hotspot/test/compiler/tiered/ConstantGettersTransitionsTest.java b/hotspot/test/compiler/tiered/ConstantGettersTransitionsTest.java new file mode 100644 index 00000000000..c55207a162e --- /dev/null +++ b/hotspot/test/compiler/tiered/ConstantGettersTransitionsTest.java @@ -0,0 +1,193 @@ +/* + * 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 java.lang.reflect.Executable; +import java.util.concurrent.Callable; + +/** + * @test ConstantGettersTransitionsTest + * @library /testlibrary /../../test/lib /compiler/whitebox + * @build TransitionsTestExecutor ConstantGettersTransitionsTest + * @run main ClassFileInstaller sun.hotspot.WhiteBox sun.hotspot.WhiteBox$WhiteBoxPermission + * @run main/othervm/timeout=240 -Xmixed -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI -XX:+TieredCompilation + * -XX:CompileCommand=compileonly,ConstantGettersTestCase$TrivialMethods::* + * TransitionsTestExecutor ConstantGettersTransitionsTest + * @summary Test the correctness of compilation level transitions for constant getters methods + */ +public class ConstantGettersTransitionsTest extends LevelTransitionTest { + public static void main(String[] args) { + assert (!CompilerWhiteBoxTest.skipOnTieredCompilation(false)); + + // run test cases + for (TestCase testCase : ConstantGettersTestCase.values()) { + new ConstantGettersTransitionsTest(testCase).runTest(); + } + } + + @Override + protected boolean isTrivial() { + return true; + } + + private ConstantGettersTransitionsTest(TestCase testCase) { + super(testCase); + } +} + +enum ConstantGettersTestCase implements CompilerWhiteBoxTest.TestCase { + ICONST_M1, + ICONST_0, + ICONST_1, + ICONST_2, + ICONST_3, + ICONST_4, + ICONST_5, + LCONST_0, + LCONST_1, + FCONST_0, + FCONST_1, + FCONST_2, + DCONST_0, + DCONST_1, + DCONST_W, + BYTE, + SHORT, + CHAR; + + private final Executable executable; + private final Callable callable; + + @Override + public Executable getExecutable() { + return executable; + } + + @Override + public Callable getCallable() { + return callable; + } + + @Override + public boolean isOsr() { + return false; + } + + private ConstantGettersTestCase() { + String name = "make" + this.name(); + this.executable = LevelTransitionTest.Helper.getMethod(TrivialMethods.class, name); + this.callable = LevelTransitionTest.Helper.getCallable(new TrivialMethods(), name); + } + + /** + * Contains methods that load constants with certain types of bytecodes + * See JVMS 2.11.2. Load and Store Instructions + * Note that it doesn't have a method for ldc_w instruction + */ + private static class TrivialMethods { + public static int makeICONST_M1() { + return -1; + } + + public static int makeICONST_0() { + return 0; + } + + public static int makeICONST_1() { + return 1; + } + + public static int makeICONST_2() { + return 2; + } + + public static int makeICONST_3() { + return 3; + } + + public static int makeICONST_4() { + return 4; + } + + public static int makeICONST_5() { + return 5; + } + + public static long makeLCONST_0() { + return 0L; + } + + public static long makeLCONST_1() { + return 1L; + } + + public static float makeFCONST_0() { + return 0F; + } + + public static float makeFCONST_1() { + return 1F; + } + + public static float makeFCONST_2() { + return 2F; + } + + public static double makeDCONST_0() { + return 0D; + } + + public static double makeDCONST_1() { + return 1D; + } + + public static double makeDCONST_W() { + // ldc2_w + return Double.MAX_VALUE; + } + + public static Object makeOBJECT() { + // aconst_null + return null; + } + + public static byte makeBYTE() { + // bipush + return (byte) 0x7F; + } + + public static short makeSHORT() { + // sipush + return (short) 0x7FFF; + } + + public static char makeCHAR() { + // ldc + return (char) 0xFFFF; + } + + public static boolean makeBOOLEAN() { + return true; + } + } +} diff --git a/hotspot/test/compiler/tiered/LevelTransitionTest.java b/hotspot/test/compiler/tiered/LevelTransitionTest.java new file mode 100644 index 00000000000..79d3626b9de --- /dev/null +++ b/hotspot/test/compiler/tiered/LevelTransitionTest.java @@ -0,0 +1,247 @@ +/* + * 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 java.lang.reflect.Executable; +import java.lang.reflect.Method; +import java.util.Objects; +import java.util.concurrent.Callable; + +/** + * @test LevelTransitionTest + * @library /testlibrary /../../test/lib /compiler/whitebox + * @build TransitionsTestExecutor LevelTransitionTest + * @run main ClassFileInstaller sun.hotspot.WhiteBox sun.hotspot.WhiteBox$WhiteBoxPermission + * @run main/othervm/timeout=240 -Xmixed -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI -XX:+TieredCompilation + * -XX:CompileCommand=compileonly,SimpleTestCase$Helper::* + * -XX:CompileCommand=compileonly,ExtendedTestCase$CompileMethodHolder::* + * TransitionsTestExecutor LevelTransitionTest + * @summary Test the correctness of compilation level transitions for different methods + */ +public class LevelTransitionTest extends TieredLevelsTest { + /** Shows if method was profiled by being executed on levels 2 or 3 */ + protected boolean isMethodProfiled; + private int transitionCount; + + public static void main(String[] args) throws Throwable { + assert (!CompilerWhiteBoxTest.skipOnTieredCompilation(false)); + + CompilerWhiteBoxTest.main(LevelTransitionTest::new, args); + // run extended test cases + for (TestCase testCase : ExtendedTestCase.values()) { + new LevelTransitionTest(testCase).runTest(); + } + } + + protected LevelTransitionTest(TestCase testCase) { + super(testCase); + isMethodProfiled = testCase.isOsr(); // OSR methods were already profiled by warmup + transitionCount = 0; + } + + @Override + protected void test() throws Exception { + checkTransitions(); + deoptimize(); + printInfo(); + if (testCase.isOsr()) { + // deoptimization makes the following transitions be unstable + // methods go to level 3 before 4 because of uncommon_trap and reprofile + return; + } + checkTransitions(); + } + + /** + * Makes and verifies transitions between compilation levels + */ + protected void checkTransitions() { + checkNotCompiled(); + boolean finish = false; + while (!finish) { + System.out.printf("Level transition #%d%n", ++transitionCount); + int newLevel; + int current = getCompLevel(); + int expected = getNextLevel(current); + if (current == expected) { + // if we are on expected level, just execute it more + // to ensure that the level won't change + System.out.printf("Method %s is already on expected level %d%n", method, expected); + compile(); + newLevel = getCompLevel(); + finish = true; + } else { + newLevel = changeCompLevel(); + finish = false; + } + System.out.printf("Method %s is compiled on level %d. Expected level is %d%n", method, newLevel, expected); + checkLevel(expected, newLevel); + printInfo(); + }; + } + + /** + * Gets next expected level for the test case on each transition. + * + * @param currentLevel a level the test case is compiled on + * @return expected compilation level + */ + protected int getNextLevel(int currentLevel) { + int nextLevel = currentLevel; + switch (currentLevel) { + case CompilerWhiteBoxTest.COMP_LEVEL_NONE: + nextLevel = isMethodProfiled ? CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION + : CompilerWhiteBoxTest.COMP_LEVEL_FULL_PROFILE; + break; + case CompilerWhiteBoxTest.COMP_LEVEL_LIMITED_PROFILE: + case CompilerWhiteBoxTest.COMP_LEVEL_FULL_PROFILE: + nextLevel = CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION; + isMethodProfiled = true; + break; + } + nextLevel = isTrivial() ? CompilerWhiteBoxTest.COMP_LEVEL_SIMPLE : nextLevel; + return Math.min(nextLevel, CompilerWhiteBoxTest.TIERED_STOP_AT_LEVEL); + } + + /** + * Determines if tested method should be handled as trivial + * + * @return {@code true} for trivial methods, {@code false} otherwise + */ + protected boolean isTrivial() { + return testCase == ExtendedTestCase.ACCESSOR_TEST + || testCase == SimpleTestCase.METHOD_TEST + || testCase == SimpleTestCase.STATIC_TEST + || (testCase == ExtendedTestCase.TRIVIAL_CODE_TEST && isMethodProfiled); + } + + /** + * Invokes {@linkplain #method} until its compilation level is changed. + * Note that if the level won't change, it will be an endless loop + * + * @return compilation level the {@linkplain #method} was compiled on + */ + protected int changeCompLevel() { + int currentLevel = getCompLevel(); + int newLevel = currentLevel; + int result = 0; + while (currentLevel == newLevel) { + result = compile(1); + if (WHITE_BOX.isMethodCompiled(method, testCase.isOsr())) { + newLevel = getCompLevel(); + } + } + return newLevel; + } + + protected static class Helper { + /** + * Gets method from a specified class using its name + * + * @param aClass type method belongs to + * @param name the name of the method + * @return {@link Method} that represents corresponding class method + */ + public static Method getMethod(Class aClass, String name) { + Method method; + try { + method = aClass.getDeclaredMethod(name); + } catch (NoSuchMethodException e) { + throw new Error("TESTBUG: Unable to get method " + name, e); + } + return method; + } + + /** + * Gets {@link Callable} that invokes given method from the given object + * + * @param object the object the specified method is invoked from + * @param name the name of the method + */ + public static Callable getCallable(Object object, String name) { + Method method = getMethod(object.getClass(), name); + return () -> { + try { + return Objects.hashCode(method.invoke(object)); + } catch (ReflectiveOperationException e) { + throw new Error("TESTBUG: Invocation failure", e); + } + }; + } + } +} + +enum ExtendedTestCase implements CompilerWhiteBoxTest.TestCase { + ACCESSOR_TEST("accessor"), + NONTRIVIAL_METHOD_TEST("nonTrivialMethod"), + TRIVIAL_CODE_TEST("trivialCode"); + + private final Executable executable; + private final Callable callable; + + @Override + public Executable getExecutable() { + return executable; + } + + @Override + public Callable getCallable() { + return callable; + } + + @Override + public boolean isOsr() { + return false; + } + + private ExtendedTestCase(String methodName) { + this.executable = LevelTransitionTest.Helper.getMethod(CompileMethodHolder.class, methodName); + this.callable = LevelTransitionTest.Helper.getCallable(new CompileMethodHolder(), methodName); + } + + private static class CompileMethodHolder { + private final int iter = 10; + private int field = 42; + + /** Non-trivial method for threshold policy: contains loops */ + public int nonTrivialMethod() { + int acc = 0; + for (int i = 0; i < iter; i++) { + acc += i; + } + return acc; + } + + /** Field accessor method */ + public int accessor() { + return field; + } + + /** Method considered as trivial by amount of code */ + public int trivialCode() { + int var = 0xBAAD_C0DE; + var *= field; + return var; + } + } +} diff --git a/hotspot/test/compiler/tiered/NonTieredLevelsTest.java b/hotspot/test/compiler/tiered/NonTieredLevelsTest.java index c8a17fc7da3..51b478f2f9c 100644 --- a/hotspot/test/compiler/tiered/NonTieredLevelsTest.java +++ b/hotspot/test/compiler/tiered/NonTieredLevelsTest.java @@ -25,7 +25,7 @@ import java.util.function.IntPredicate; /** * @test NonTieredLevelsTest - * @library /testlibrary /testlibrary/whitebox /compiler/whitebox + * @library /testlibrary /../../test/lib /compiler/whitebox * @build NonTieredLevelsTest * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission @@ -55,9 +55,7 @@ public class NonTieredLevelsTest extends CompLevelsTest { } public static void main(String[] args) throws Exception { - if (TIERED_COMPILATION) { - System.err.println("Test isn't applicable w/ enabled " - + "TieredCompilation. Skip test."); + if (CompilerWhiteBoxTest.skipOnTieredCompilation(true)) { return; } CompilerWhiteBoxTest.main(NonTieredLevelsTest::new, args); diff --git a/hotspot/test/compiler/tiered/TieredLevelsTest.java b/hotspot/test/compiler/tiered/TieredLevelsTest.java index 5970892e640..1411a07b3ab 100644 --- a/hotspot/test/compiler/tiered/TieredLevelsTest.java +++ b/hotspot/test/compiler/tiered/TieredLevelsTest.java @@ -23,7 +23,7 @@ /** * @test TieredLevelsTest - * @library /testlibrary /testlibrary/whitebox /compiler/whitebox + * @library /testlibrary /../../test/lib /compiler/whitebox * @build TieredLevelsTest * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission @@ -35,16 +35,14 @@ * @author igor.ignatyev@oracle.com */ public class TieredLevelsTest extends CompLevelsTest { - public static void main(String[] args) throws Exception { - if (!TIERED_COMPILATION) { - System.err.println("Test isn't applicable w/ disabled " - + "TieredCompilation. Skip test."); + public static void main(String[] args) throws Exception, Throwable { + if (CompilerWhiteBoxTest.skipOnTieredCompilation(false)) { return; } CompilerWhiteBoxTest.main(TieredLevelsTest::new, args); } - private TieredLevelsTest(TestCase testCase) { + protected TieredLevelsTest(TestCase testCase) { super(testCase); // to prevent inlining of #method WHITE_BOX.testSetDontInlineMethod(method, true); @@ -77,14 +75,18 @@ public class TieredLevelsTest extends CompLevelsTest { } } - @Override protected void checkLevel(int expected, int actual) { if (expected == COMP_LEVEL_FULL_PROFILE && actual == COMP_LEVEL_LIMITED_PROFILE) { // for simple method full_profile may be replaced by limited_profile + if (IS_VERBOSE) { + System.out.printf("Level check: full profiling was replaced " + + "by limited profiling. Expected: %d, actual:%d", + expected, actual); + } return; } super.checkLevel(expected, actual); - } + } } diff --git a/hotspot/test/compiler/tiered/TransitionsTestExecutor.java b/hotspot/test/compiler/tiered/TransitionsTestExecutor.java new file mode 100644 index 00000000000..15f731b503f --- /dev/null +++ b/hotspot/test/compiler/tiered/TransitionsTestExecutor.java @@ -0,0 +1,66 @@ +/* + * 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 com.oracle.java.testlibrary.OutputAnalyzer; +import com.oracle.java.testlibrary.ProcessTools; + +import java.lang.management.ManagementFactory; +import java.lang.management.RuntimeMXBean; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * Executes given test in a separate VM with enabled Tiered Compilation for + * CompilationPolicyChoice 2 and 3 + */ +public class TransitionsTestExecutor { + public static void main(String[] args) throws Throwable { + if (CompilerWhiteBoxTest.skipOnTieredCompilation(false)) { + return; + } + if (args.length != 1) { + throw new Error("TESTBUG: Test name should be specified"); + } + executeTestFor(2, args[0]); + executeTestFor(3, args[0]); + } + + private static void executeTestFor(int compilationPolicy, String testName) throws Throwable { + String policy = "-XX:CompilationPolicyChoice=" + compilationPolicy; + + // Get runtime arguments including VM options given to this executor + RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean(); + List vmArgs = runtime.getInputArguments(); + + // Construct execution command with compilation policy choice and test name + List args = new ArrayList<>(vmArgs); + Collections.addAll(args, policy, testName); + + OutputAnalyzer out = ProcessTools.executeTestJvm(args.toArray(new String[args.size()])); + int exitCode = out.getExitValue(); + if (exitCode != 0) { + throw new Error("Test execution failed with exit code " + exitCode); + } + } +} diff --git a/hotspot/test/compiler/types/correctness/CorrectnessTest.java b/hotspot/test/compiler/types/correctness/CorrectnessTest.java index 3d002c3e660..c5239df8942 100644 --- a/hotspot/test/compiler/types/correctness/CorrectnessTest.java +++ b/hotspot/test/compiler/types/correctness/CorrectnessTest.java @@ -24,7 +24,7 @@ /* * @test CorrectnessTest * @bug 8038418 - * @library /testlibrary /testlibrary/whitebox + * @library /testlibrary /../../test/lib * @ignore 8066173 * @compile execution/TypeConflict.java execution/TypeProfile.java * execution/MethodHandleDelegate.java diff --git a/hotspot/test/compiler/types/correctness/OffTest.java b/hotspot/test/compiler/types/correctness/OffTest.java index 86221c53c54..0125fe76af5 100644 --- a/hotspot/test/compiler/types/correctness/OffTest.java +++ b/hotspot/test/compiler/types/correctness/OffTest.java @@ -24,7 +24,7 @@ /* * @test CorrectnessTest * @bug 8038418 - * @library /testlibrary /testlibrary/whitebox + * @library /testlibrary /../../test/lib * @ignore 8066173 * @compile execution/TypeConflict.java execution/TypeProfile.java * execution/MethodHandleDelegate.java diff --git a/hotspot/test/compiler/uncommontrap/8009761/Test8009761.java b/hotspot/test/compiler/uncommontrap/8009761/Test8009761.java index 46aad286840..aff4947ee74 100644 --- a/hotspot/test/compiler/uncommontrap/8009761/Test8009761.java +++ b/hotspot/test/compiler/uncommontrap/8009761/Test8009761.java @@ -27,7 +27,7 @@ import java.lang.reflect.Method; /* * @test * @bug 8009761 - * @library /testlibrary /testlibrary/whitebox + * @library /testlibrary /../../test/lib * @summary Deoptimization on sparc doesn't set Llast_SP correctly in the interpreter frames it creates * @build Test8009761 * @run main ClassFileInstaller sun.hotspot.WhiteBox diff --git a/hotspot/test/compiler/uncommontrap/TestDeoptOOM.java b/hotspot/test/compiler/uncommontrap/TestDeoptOOM.java new file mode 100644 index 00000000000..5342582fb00 --- /dev/null +++ b/hotspot/test/compiler/uncommontrap/TestDeoptOOM.java @@ -0,0 +1,426 @@ +/* + * 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 6898462 + * @summary failed reallocations of scalar replaced objects during deoptimization causes crash + * @run main/othervm -XX:-BackgroundCompilation -XX:CompileCommand=exclude,TestDeoptOOM::main -XX:CompileCommand=exclude,TestDeoptOOM::m9_1 -Xmx128M TestDeoptOOM + * + */ + +public class TestDeoptOOM { + + long f1; + long f2; + long f3; + long f4; + long f5; + + static class LinkedList { + LinkedList l; + long[] array; + LinkedList(LinkedList l, int size) { + array = new long[size]; + this.l = l; + } + } + + static LinkedList ll; + + static void consume_all_memory() { + int size = 128 * 1024 * 1024; + while(size > 0) { + try { + while(true) { + ll = new LinkedList(ll, size); + } + } catch(OutOfMemoryError oom) { + } + size = size / 2; + } + } + + static void free_memory() { + ll = null; + } + + static TestDeoptOOM m1(boolean deopt) { + try { + TestDeoptOOM tdoom = new TestDeoptOOM(); + if (deopt) { + return tdoom; + } + } catch(OutOfMemoryError oom) { + free_memory(); + System.out.println("OOM caught in m1"); + } + return null; + } + + static TestDeoptOOM m2_1(boolean deopt) { + try { + TestDeoptOOM tdoom = new TestDeoptOOM(); + if (deopt) { + return tdoom; + } + } catch(OutOfMemoryError oom) { + free_memory(); + System.out.println("OOM caught in m2_1"); + } + return null; + } + + static TestDeoptOOM m2(boolean deopt) { + try { + return m2_1(deopt); + } catch(OutOfMemoryError oom) { + free_memory(); + System.out.println("OOM caught in m2"); + } + return null; + } + + static TestDeoptOOM m3_3(boolean deopt) { + try { + TestDeoptOOM tdoom = new TestDeoptOOM(); + if (deopt) { + return tdoom; + } + } catch(OutOfMemoryError oom) { + free_memory(); + System.out.println("OOM caught in m3_3"); + } + return null; + } + + static boolean m3_2(boolean deopt) { + try { + return m3_3(deopt) != null; + } catch(OutOfMemoryError oom) { + free_memory(); + System.out.println("OOM caught in m3_2"); + } + return false; + } + + static TestDeoptOOM m3_1(boolean deopt) { + try { + TestDeoptOOM tdoom = new TestDeoptOOM(); + if (m3_2(deopt)) { + return tdoom; + } + } catch(OutOfMemoryError oom) { + free_memory(); + System.out.println("OOM caught in m3_1"); + } + return null; + } + + static TestDeoptOOM m3(boolean deopt) { + try { + return m3_1(deopt); + } catch(OutOfMemoryError oom) { + free_memory(); + System.out.println("OOM caught in m3"); + } + return null; + } + + static TestDeoptOOM m4(boolean deopt) { + try { + TestDeoptOOM tdoom = new TestDeoptOOM(); + if (deopt) { + tdoom.f1 = 1l; + tdoom.f2 = 2l; + tdoom.f3 = 3l; + return tdoom; + } + } catch(OutOfMemoryError oom) { + free_memory(); + System.out.println("OOM caught in m4"); + } + return null; + } + + static TestDeoptOOM m5(boolean deopt) { + try { + TestDeoptOOM tdoom = new TestDeoptOOM(); + synchronized(tdoom) { + if (deopt) { + return tdoom; + } + } + } catch(OutOfMemoryError oom) { + free_memory(); + System.out.println("OOM caught in m5"); + } + return null; + } + + synchronized TestDeoptOOM m6_1(boolean deopt) { + if (deopt) { + return this; + } + return null; + } + + static TestDeoptOOM m6(boolean deopt) { + try { + TestDeoptOOM tdoom = new TestDeoptOOM(); + return tdoom.m6_1(deopt); + } catch(OutOfMemoryError oom) { + free_memory(); + System.out.println("OOM caught in m6"); + } + return null; + } + + static TestDeoptOOM m7_1(boolean deopt, Object lock) { + try { + synchronized(lock) { + TestDeoptOOM tdoom = new TestDeoptOOM(); + if (deopt) { + return tdoom; + } + } + } catch(OutOfMemoryError oom) { + free_memory(); + System.out.println("OOM caught in m7_1"); + } + return null; + } + + static TestDeoptOOM m7(boolean deopt, Object lock) { + try { + return m7_1(deopt, lock); + } catch(OutOfMemoryError oom) { + free_memory(); + System.out.println("OOM caught in m7"); + } + return null; + } + + static class A { + long f1; + long f2; + long f3; + long f4; + long f5; + } + + static class B { + long f1; + long f2; + long f3; + long f4; + long f5; + + A a; + } + + static B m8(boolean deopt) { + try { + A a = new A(); + B b = new B(); + b.a = a; + if (deopt) { + return b; + } + } catch(OutOfMemoryError oom) { + free_memory(); + System.out.println("OOM caught in m8"); + } + return null; + } + + static void m9_1(int i) { + if (i > 90000) { + consume_all_memory(); + } + } + + static TestDeoptOOM m9() { + try { + for (int i = 0; i < 100000; i++) { + TestDeoptOOM tdoom = new TestDeoptOOM(); + m9_1(i); + if (i > 90000) { + return tdoom; + } + } + } catch(OutOfMemoryError oom) { + free_memory(); + System.out.println("OOM caught in m1"); + } + return null; + } + + public static void main(String[] args) { + for (int i = 0; i < 20000; i++) { + m1(false); + } + + consume_all_memory(); + + try { + m1(true); + } catch(OutOfMemoryError oom) { + free_memory(); + System.out.println("OOM caught in main " + oom.getMessage()); + } + + free_memory(); + + for (int i = 0; i < 20000; i++) { + m2(false); + } + + consume_all_memory(); + + try { + m2(true); + } catch(OutOfMemoryError oom) { + free_memory(); + System.out.println("OOM caught in main"); + } + + free_memory(); + + for (int i = 0; i < 20000; i++) { + m3(false); + } + + consume_all_memory(); + + try { + m3(true); + } catch(OutOfMemoryError oom) { + free_memory(); + System.out.println("OOM caught in main"); + } + + free_memory(); + + for (int i = 0; i < 20000; i++) { + m4(false); + } + + consume_all_memory(); + + try { + m4(true); + } catch(OutOfMemoryError oom) { + free_memory(); + System.out.println("OOM caught in main"); + } + + free_memory(); + + for (int i = 0; i < 20000; i++) { + m5(false); + } + + consume_all_memory(); + + try { + m5(true); + } catch(OutOfMemoryError oom) { + free_memory(); + System.out.println("OOM caught in main"); + } + + free_memory(); + + for (int i = 0; i < 20000; i++) { + m6(false); + } + + consume_all_memory(); + + try { + m6(true); + } catch(OutOfMemoryError oom) { + free_memory(); + System.out.println("OOM caught in main"); + } + + free_memory(); + + final Object lock = new Object(); + + for (int i = 0; i < 20000; i++) { + m7(false, lock); + } + + consume_all_memory(); + + try { + m7(true, lock); + } catch(OutOfMemoryError oom) { + free_memory(); + System.out.println("OOM caught in main"); + } + + free_memory(); + + Thread thread = new Thread() { + public void run() { + System.out.println("Acquiring lock"); + synchronized(lock) { + System.out.println("Lock acquired"); + } + System.out.println("Lock released"); + } + }; + thread.start(); + try { + thread.join(); + } catch(InterruptedException ie) { + } + + for (int i = 0; i < 20000; i++) { + m8(false); + } + + consume_all_memory(); + + try { + m8(true); + } catch(OutOfMemoryError oom) { + free_memory(); + System.out.println("OOM caught in main"); + } + + free_memory(); + + try { + m9(); + } catch(OutOfMemoryError oom) { + free_memory(); + System.out.println("OOM caught in main"); + } + + free_memory(); + } +} diff --git a/hotspot/test/compiler/uncommontrap/TraceDeoptimizationNoRealloc.java b/hotspot/test/compiler/uncommontrap/TraceDeoptimizationNoRealloc.java new file mode 100644 index 00000000000..563bbbbe00e --- /dev/null +++ b/hotspot/test/compiler/uncommontrap/TraceDeoptimizationNoRealloc.java @@ -0,0 +1,47 @@ +/* + * 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 8067144 + * @summary -XX:+TraceDeoptimization tries to print realloc'ed objects even when there are none + * @run main/othervm -XX:-BackgroundCompilation -XX:-UseOnStackReplacement -XX:+IgnoreUnrecognizedVMOptions -XX:+TraceDeoptimization TraceDeoptimizationNoRealloc + * + */ + +public class TraceDeoptimizationNoRealloc { + + static void m(boolean some_condition) { + if (some_condition) { + return; + } + } + + + static public void main(String[] args) { + for (int i = 0; i < 20000; i++) { + m(false); + } + m(true); + } +} diff --git a/hotspot/test/compiler/whitebox/AllocationCodeBlobTest.java b/hotspot/test/compiler/whitebox/AllocationCodeBlobTest.java index a8648e7a3e5..56def58f5c3 100644 --- a/hotspot/test/compiler/whitebox/AllocationCodeBlobTest.java +++ b/hotspot/test/compiler/whitebox/AllocationCodeBlobTest.java @@ -34,7 +34,7 @@ import com.oracle.java.testlibrary.InfiniteLoop; /* * @test AllocationCodeBlobTest * @bug 8059624 8064669 - * @library /testlibrary /testlibrary/whitebox + * @library /testlibrary /../../test/lib * @build AllocationCodeBlobTest * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/compiler/whitebox/ClearMethodStateTest.java b/hotspot/test/compiler/whitebox/ClearMethodStateTest.java index 9adaefd0d33..8a13a689c1d 100644 --- a/hotspot/test/compiler/whitebox/ClearMethodStateTest.java +++ b/hotspot/test/compiler/whitebox/ClearMethodStateTest.java @@ -26,7 +26,7 @@ import java.util.function.Function; /* * @test ClearMethodStateTest * @bug 8006683 8007288 8022832 - * @library /testlibrary /testlibrary/whitebox + * @library /testlibrary /../../test/lib * @build ClearMethodStateTest * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/compiler/whitebox/CompilerWhiteBoxTest.java b/hotspot/test/compiler/whitebox/CompilerWhiteBoxTest.java index efacb470d89..1972b35eb1d 100644 --- a/hotspot/test/compiler/whitebox/CompilerWhiteBoxTest.java +++ b/hotspot/test/compiler/whitebox/CompilerWhiteBoxTest.java @@ -38,19 +38,19 @@ import java.util.function.Function; */ public abstract class CompilerWhiteBoxTest { /** {@code CompLevel::CompLevel_none} -- Interpreter */ - protected static int COMP_LEVEL_NONE = 0; + protected static final int COMP_LEVEL_NONE = 0; /** {@code CompLevel::CompLevel_any}, {@code CompLevel::CompLevel_all} */ - protected static int COMP_LEVEL_ANY = -1; + protected static final int COMP_LEVEL_ANY = -1; /** {@code CompLevel::CompLevel_simple} -- C1 */ - protected static int COMP_LEVEL_SIMPLE = 1; + protected static final int COMP_LEVEL_SIMPLE = 1; /** {@code CompLevel::CompLevel_limited_profile} -- C1, invocation & backedge counters */ - protected static int COMP_LEVEL_LIMITED_PROFILE = 2; + protected static final int COMP_LEVEL_LIMITED_PROFILE = 2; /** {@code CompLevel::CompLevel_full_profile} -- C1, invocation & backedge counters + mdo */ - protected static int COMP_LEVEL_FULL_PROFILE = 3; + protected static final int COMP_LEVEL_FULL_PROFILE = 3; /** {@code CompLevel::CompLevel_full_optimization} -- C2 or Shark */ - protected static int COMP_LEVEL_FULL_OPTIMIZATION = 4; + protected static final int COMP_LEVEL_FULL_OPTIMIZATION = 4; /** Maximal value for CompLevel */ - protected static int COMP_LEVEL_MAX = COMP_LEVEL_FULL_OPTIMIZATION; + protected static final int COMP_LEVEL_MAX = COMP_LEVEL_FULL_OPTIMIZATION; /** Instance of WhiteBox */ protected static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox(); @@ -336,14 +336,22 @@ public abstract class CompilerWhiteBoxTest { System.out.printf("%n%s:%n", method); System.out.printf("\tcompilable:\t%b%n", WHITE_BOX.isMethodCompilable(method, COMP_LEVEL_ANY, false)); - System.out.printf("\tcompiled:\t%b%n", - WHITE_BOX.isMethodCompiled(method, false)); + boolean isCompiled = WHITE_BOX.isMethodCompiled(method, false); + System.out.printf("\tcompiled:\t%b%n", isCompiled); + if (isCompiled) { + System.out.printf("\tcompile_id:\t%d%n", + NMethod.get(method, false).compile_id); + } System.out.printf("\tcomp_level:\t%d%n", WHITE_BOX.getMethodCompilationLevel(method, false)); System.out.printf("\tosr_compilable:\t%b%n", WHITE_BOX.isMethodCompilable(method, COMP_LEVEL_ANY, true)); - System.out.printf("\tosr_compiled:\t%b%n", - WHITE_BOX.isMethodCompiled(method, true)); + isCompiled = WHITE_BOX.isMethodCompiled(method, true); + System.out.printf("\tosr_compiled:\t%b%n", isCompiled); + if (isCompiled) { + System.out.printf("\tosr_compile_id:\t%d%n", + NMethod.get(method, true).compile_id); + } System.out.printf("\tosr_comp_level:\t%d%n", WHITE_BOX.getMethodCompilationLevel(method, true)); System.out.printf("\tin_queue:\t%b%n", @@ -426,6 +434,22 @@ public abstract class CompilerWhiteBoxTest { } return result; } + + /** + * Skip the test for the specified value of Tiered Compilation + * @param value of TieredCompilation the test should not run with + * @return {@code true} if the test should be skipped, + * {@code false} otherwise + */ + protected static boolean skipOnTieredCompilation(boolean value) { + if (value == CompilerWhiteBoxTest.TIERED_COMPILATION) { + System.err.println("Test isn't applicable w/ " + + (value ? "enabled" : "disabled") + + "TieredCompilation. Skip test."); + return true; + } + return false; + } } enum SimpleTestCase implements CompilerWhiteBoxTest.TestCase { diff --git a/hotspot/test/compiler/whitebox/DeoptimizeAllTest.java b/hotspot/test/compiler/whitebox/DeoptimizeAllTest.java index d88bc5b9951..910eb95dc99 100644 --- a/hotspot/test/compiler/whitebox/DeoptimizeAllTest.java +++ b/hotspot/test/compiler/whitebox/DeoptimizeAllTest.java @@ -24,7 +24,7 @@ /* * @test DeoptimizeAllTest * @bug 8006683 8007288 8022832 - * @library /testlibrary /testlibrary/whitebox + * @library /testlibrary /../../test/lib * @build DeoptimizeAllTest * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/compiler/whitebox/DeoptimizeFramesTest.java b/hotspot/test/compiler/whitebox/DeoptimizeFramesTest.java new file mode 100644 index 00000000000..16a291562fc --- /dev/null +++ b/hotspot/test/compiler/whitebox/DeoptimizeFramesTest.java @@ -0,0 +1,157 @@ +/* + * 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 DeoptimizeFramesTest + * @bug 8028595 + * @library /testlibrary /../../test/lib + * @build DeoptimizeFramesTest + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI -Xmixed + * -XX:CompileCommand=compileonly,DeoptimizeFramesTest$TestCaseImpl::method + * -XX:-DeoptimizeRandom DeoptimizeFramesTest true + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI -Xmixed + * -XX:CompileCommand=compileonly,DeoptimizeFramesTest$TestCaseImpl::method + * -XX:-DeoptimizeRandom DeoptimizeFramesTest false + * @summary testing of WB::deoptimizeFrames() + */ +import java.lang.reflect.Executable; +import java.util.concurrent.Callable; +import java.util.concurrent.Phaser; + +import sun.hotspot.code.NMethod; +import com.oracle.java.testlibrary.Asserts; +import com.oracle.java.testlibrary.InfiniteLoop; + +public class DeoptimizeFramesTest extends CompilerWhiteBoxTest { + private final boolean makeNotEntrant; + private final Phaser phaser; + + private DeoptimizeFramesTest(boolean makeNotEntrant, Phaser phaser) { + super(new TestCaseImpl(phaser)); + // to prevent inlining of #method + WHITE_BOX.testSetDontInlineMethod(method, true); + this.makeNotEntrant = makeNotEntrant; + this.phaser = phaser; + System.out.printf("DeoptimizeFramesTest(makeNotEntrant = %b)%n", + makeNotEntrant); + } + + public static void main(String[] args) throws Exception { + Asserts.assertEQ(args.length, 1, + "[TESTBUG] args should contain 1 element"); + new DeoptimizeFramesTest(Boolean.valueOf(args[0]), new Phaser()).runTest(); + } + + @Override + protected void test() throws Exception { + compile(); + checkCompiled(); + NMethod nm = NMethod.get(method, testCase.isOsr()); + + WHITE_BOX.deoptimizeFrames(makeNotEntrant); + // #method should still be compiled, since it didn't have frames on stack + checkCompiled(); + NMethod nm2 = NMethod.get(method, testCase.isOsr()); + Asserts.assertEQ(nm.compile_id, nm2.compile_id, + "should be the same nmethod"); + + phaser.register(); + Thread t = new Thread(() -> compile(1)); + t.start(); + // pass 1st phase, #method is on stack + int p = phaser.arriveAndAwaitAdvance(); + WHITE_BOX.deoptimizeFrames(makeNotEntrant); + // pass 2nd phase, #method can exit + phaser.awaitAdvance(phaser.arriveAndDeregister()); + + try { + t.join(); + } catch (InterruptedException e) { + throw new Error("method '" + method + "' is still executing", e); + } + + // invoke one more time to recompile not entrant if any + compile(1); + + nm2 = NMethod.get(method, testCase.isOsr()); + if (makeNotEntrant) { + if (nm2 != null) { + Asserts.assertNE(nm.compile_id, nm2.compile_id, + String.format("compilation %d can't be available", nm.compile_id)); + } + } else { + Asserts.assertEQ(nm.compile_id, nm2.compile_id, "should be the same nmethod"); + } + } + + + private static class TestCaseImpl implements TestCase { + private static final Executable EXECUTABLE; + static { + try { + EXECUTABLE = TestCaseImpl.class.getDeclaredMethod("method"); + } catch (NoSuchMethodException e) { + throw new Error("[TESTBUG] method not found", e); + } + } + + private final Phaser phaser; + + public TestCaseImpl(Phaser phaser) { + this.phaser = phaser; + phaser.register(); + } + + @Override + public String name() { + return "2phases"; + } + + @Override + public Executable getExecutable() { + return EXECUTABLE; + } + + @Override + public Callable getCallable() { + return () -> { + return method(); + }; + } + + @Override + public boolean isOsr() { + return false; + } + + private int method() { + phaser.arriveAndAwaitAdvance(); + phaser.arriveAndAwaitAdvance(); + return 0; + } + } +} diff --git a/hotspot/test/compiler/whitebox/DeoptimizeMethodTest.java b/hotspot/test/compiler/whitebox/DeoptimizeMethodTest.java index 3716e75e247..667e3d56ae7 100644 --- a/hotspot/test/compiler/whitebox/DeoptimizeMethodTest.java +++ b/hotspot/test/compiler/whitebox/DeoptimizeMethodTest.java @@ -24,7 +24,7 @@ /* * @test DeoptimizeMethodTest * @bug 8006683 8007288 8022832 - * @library /testlibrary /testlibrary/whitebox + * @library /testlibrary /../../test/lib * @build DeoptimizeMethodTest * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/compiler/whitebox/DeoptimizeMultipleOSRTest.java b/hotspot/test/compiler/whitebox/DeoptimizeMultipleOSRTest.java index f81d199a8d0..b4d729bedbd 100644 --- a/hotspot/test/compiler/whitebox/DeoptimizeMultipleOSRTest.java +++ b/hotspot/test/compiler/whitebox/DeoptimizeMultipleOSRTest.java @@ -28,7 +28,7 @@ import java.lang.reflect.Method; /* * @test DeoptimizeMultipleOSRTest * @bug 8061817 - * @library /testlibrary /testlibrary/whitebox + * @library /testlibrary /../../test/lib * @build DeoptimizeMultipleOSRTest * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/compiler/whitebox/EnqueueMethodForCompilationTest.java b/hotspot/test/compiler/whitebox/EnqueueMethodForCompilationTest.java index a70c738ae67..f068eeb1226 100644 --- a/hotspot/test/compiler/whitebox/EnqueueMethodForCompilationTest.java +++ b/hotspot/test/compiler/whitebox/EnqueueMethodForCompilationTest.java @@ -24,7 +24,7 @@ /* * @test EnqueueMethodForCompilationTest * @bug 8006683 8007288 8022832 - * @library /testlibrary /testlibrary/whitebox + * @library /testlibrary /../../test/lib * @build EnqueueMethodForCompilationTest * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/compiler/whitebox/ForceNMethodSweepTest.java b/hotspot/test/compiler/whitebox/ForceNMethodSweepTest.java index 9617465ca5b..5038e7cfa8f 100644 --- a/hotspot/test/compiler/whitebox/ForceNMethodSweepTest.java +++ b/hotspot/test/compiler/whitebox/ForceNMethodSweepTest.java @@ -34,7 +34,7 @@ import com.oracle.java.testlibrary.InfiniteLoop; /* * @test * @bug 8059624 8064669 - * @library /testlibrary /testlibrary/whitebox + * @library /testlibrary /../../test/lib * @build ForceNMethodSweepTest * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/compiler/whitebox/GetCodeHeapEntriesTest.java b/hotspot/test/compiler/whitebox/GetCodeHeapEntriesTest.java index 0fb35424efc..9a3036346ac 100644 --- a/hotspot/test/compiler/whitebox/GetCodeHeapEntriesTest.java +++ b/hotspot/test/compiler/whitebox/GetCodeHeapEntriesTest.java @@ -33,7 +33,7 @@ import com.oracle.java.testlibrary.Asserts; /* * @test GetCodeHeapEntriesTest * @bug 8059624 - * @library /testlibrary /testlibrary/whitebox + * @library /testlibrary /../../test/lib * @build GetCodeHeapEntriesTest * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/compiler/whitebox/GetNMethodTest.java b/hotspot/test/compiler/whitebox/GetNMethodTest.java index 45ce48fc6ec..28d0e4312f9 100644 --- a/hotspot/test/compiler/whitebox/GetNMethodTest.java +++ b/hotspot/test/compiler/whitebox/GetNMethodTest.java @@ -29,7 +29,7 @@ import com.oracle.java.testlibrary.Asserts; /* * @test GetNMethodTest * @bug 8038240 - * @library /testlibrary /testlibrary/whitebox + * @library /testlibrary /../../test/lib * @build GetNMethodTest * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/compiler/whitebox/IsMethodCompilableTest.java b/hotspot/test/compiler/whitebox/IsMethodCompilableTest.java index 2f301c75520..0017d0ca1ed 100644 --- a/hotspot/test/compiler/whitebox/IsMethodCompilableTest.java +++ b/hotspot/test/compiler/whitebox/IsMethodCompilableTest.java @@ -24,7 +24,7 @@ /* * @test IsMethodCompilableTest * @bug 8007270 8006683 8007288 8022832 - * @library /testlibrary /testlibrary/whitebox /testlibrary/com/oracle/java/testlibrary + * @library /testlibrary /../../test/lib /testlibrary/com/oracle/java/testlibrary * @build IsMethodCompilableTest * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/compiler/whitebox/LockCompilationTest.java b/hotspot/test/compiler/whitebox/LockCompilationTest.java index 5f16481a6de..25080fe606a 100644 --- a/hotspot/test/compiler/whitebox/LockCompilationTest.java +++ b/hotspot/test/compiler/whitebox/LockCompilationTest.java @@ -24,7 +24,7 @@ /* * @test LockCompilationTest * @bug 8059624 - * @library /testlibrary /testlibrary/whitebox + * @library /testlibrary /../../test/lib * @build LockCompilationTest * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/compiler/whitebox/MakeMethodNotCompilableTest.java b/hotspot/test/compiler/whitebox/MakeMethodNotCompilableTest.java index 6a79d8a5dba..ca5ff1f709b 100644 --- a/hotspot/test/compiler/whitebox/MakeMethodNotCompilableTest.java +++ b/hotspot/test/compiler/whitebox/MakeMethodNotCompilableTest.java @@ -24,7 +24,7 @@ /* * @test MakeMethodNotCompilableTest * @bug 8012322 8006683 8007288 8022832 - * @library /testlibrary /testlibrary/whitebox + * @library /testlibrary /../../test/lib * @build MakeMethodNotCompilableTest * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/compiler/whitebox/SetDontInlineMethodTest.java b/hotspot/test/compiler/whitebox/SetDontInlineMethodTest.java index 67e323ebce5..0c4ee8d104e 100644 --- a/hotspot/test/compiler/whitebox/SetDontInlineMethodTest.java +++ b/hotspot/test/compiler/whitebox/SetDontInlineMethodTest.java @@ -24,7 +24,7 @@ /* * @test SetDontInlineMethodTest * @bug 8006683 8007288 8022832 - * @library /testlibrary /testlibrary/whitebox + * @library /testlibrary /../../test/lib * @build SetDontInlineMethodTest * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/compiler/whitebox/SetForceInlineMethodTest.java b/hotspot/test/compiler/whitebox/SetForceInlineMethodTest.java index 560ad029604..caca0f6fbb4 100644 --- a/hotspot/test/compiler/whitebox/SetForceInlineMethodTest.java +++ b/hotspot/test/compiler/whitebox/SetForceInlineMethodTest.java @@ -24,7 +24,7 @@ /* * @test SetForceInlineMethodTest * @bug 8006683 8007288 8022832 - * @library /testlibrary /testlibrary/whitebox + * @library /testlibrary /../../test/lib * @build SetForceInlineMethodTest * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/gc/TestCardTablePageCommits.java b/hotspot/test/gc/TestCardTablePageCommits.java new file mode 100644 index 00000000000..0dec3d83b93 --- /dev/null +++ b/hotspot/test/gc/TestCardTablePageCommits.java @@ -0,0 +1,49 @@ +/* +* 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 com.oracle.java.testlibrary.JDKToolFinder; +import com.oracle.java.testlibrary.OutputAnalyzer; +import com.oracle.java.testlibrary.ProcessTools; +import com.oracle.java.testlibrary.Platform; + +/* + * @test TestCardTablePageCommits + * @key gc + * @bug 8059066 + * @summary Tests that the card table does not commit the same page twice + * @library /testlibrary + * @run driver TestCardTablePageCommits + */ +public class TestCardTablePageCommits { + public static void main(String args[]) throws Exception { + // The test is run with a small heap to make sure all pages in the card + // table gets committed. Need 8 MB heap to trigger the bug on SPARC + // because of 8kB pages, assume 4 KB pages for all other CPUs. + String Xmx = Platform.isSparc() ? "-Xmx8m" : "-Xmx4m"; + + String[] opts = {Xmx, "-XX:NativeMemoryTracking=detail", "-XX:+UseParallelGC", "-version"}; + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(opts); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldHaveExitValue(0); + } +} diff --git a/hotspot/test/gc/TestSmallHeap.java b/hotspot/test/gc/TestSmallHeap.java new file mode 100644 index 00000000000..321e33bf3b6 --- /dev/null +++ b/hotspot/test/gc/TestSmallHeap.java @@ -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 TestSmallHeap + * @bug 8067438 + * @requires vm.gc=="null" + * @summary Verify that starting the VM with a small heap works + * @library /testlibrary + * @run main/othervm -Xmx4m -XX:+UseParallelGC TestSmallHeap + * @run main/othervm -Xmx4m -XX:+UseSerialGC TestSmallHeap + * @run main/othervm -Xmx4m -XX:+UseG1GC TestSmallHeap + * @run main/othervm -Xmx4m -XX:+UseConcMarkSweepGC -XX:CMSMarkStackSizeMax=1032 TestSmallHeap + * + * Note: It would be nice to verify the minimal supported heap size here, + * but that turns out to be quite tricky since we align the heap size based + * on the card table size. And the card table size is aligned based on the + * minimal pages size provided by the os. This means that on most platforms, + * where the minimal page size is 4k, we get a minimal heap size of 2m but + * on Solaris/Sparc we have a page size of 8k and get a minimal heap size + * of 8m. + * There is also no check in the VM for verifying that the maximum heap size + * is larger than the supported minimal heap size. This means that specifying + * -Xmx1m on the command line is fine but will give a heap of 2m (or 4m). + * To work around these rather strange behaviors this test uses 4m for all + * platforms. + */ + +import sun.management.ManagementFactoryHelper; +import static com.oracle.java.testlibrary.Asserts.*; + +public class TestSmallHeap { + + public static void main(String[] args) { + String maxHeap = ManagementFactoryHelper.getDiagnosticMXBean().getVMOption("MaxHeapSize").getValue(); + String expectedMaxHeap = "4194304"; + assertEQ(maxHeap, expectedMaxHeap); + } +} diff --git a/hotspot/test/gc/arguments/TestCMSHeapSizeFlags.java b/hotspot/test/gc/arguments/TestCMSHeapSizeFlags.java index f142964e380..01fed8df0dc 100644 --- a/hotspot/test/gc/arguments/TestCMSHeapSizeFlags.java +++ b/hotspot/test/gc/arguments/TestCMSHeapSizeFlags.java @@ -26,7 +26,7 @@ * @key gc * @bug 8006088 * @summary Tests argument processing for initial and maximum heap size for the CMS collector - * @library /testlibrary /testlibrary/whitebox + * @library /testlibrary /../../test/lib * @build TestCMSHeapSizeFlags TestMaxHeapSizeTools * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/gc/arguments/TestG1HeapSizeFlags.java b/hotspot/test/gc/arguments/TestG1HeapSizeFlags.java index fabc4f02192..daa02c455f6 100644 --- a/hotspot/test/gc/arguments/TestG1HeapSizeFlags.java +++ b/hotspot/test/gc/arguments/TestG1HeapSizeFlags.java @@ -26,7 +26,7 @@ * @key gc * @bug 8006088 * @summary Tests argument processing for initial and maximum heap size for the G1 collector - * @library /testlibrary /testlibrary/whitebox + * @library /testlibrary /../../test/lib * @build TestG1HeapSizeFlags TestMaxHeapSizeTools * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/gc/arguments/TestMinInitialErgonomics.java b/hotspot/test/gc/arguments/TestMinInitialErgonomics.java index 1f90bec1e01..3b297266cbe 100644 --- a/hotspot/test/gc/arguments/TestMinInitialErgonomics.java +++ b/hotspot/test/gc/arguments/TestMinInitialErgonomics.java @@ -26,7 +26,7 @@ * @key gc * @bug 8006088 * @summary Test ergonomics decisions related to minimum and initial heap size. - * @library /testlibrary /testlibrary/whitebox + * @library /testlibrary /../../test/lib * @build TestMinInitialErgonomics TestMaxHeapSizeTools * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/gc/arguments/TestParallelHeapSizeFlags.java b/hotspot/test/gc/arguments/TestParallelHeapSizeFlags.java index c9837f50b7c..8276e68c234 100644 --- a/hotspot/test/gc/arguments/TestParallelHeapSizeFlags.java +++ b/hotspot/test/gc/arguments/TestParallelHeapSizeFlags.java @@ -27,7 +27,7 @@ * @bug 8006088 * @summary Tests argument processing for initial and maximum heap size for the * parallel collectors. - * @library /testlibrary /testlibrary/whitebox + * @library /testlibrary /../../test/lib * @build TestParallelHeapSizeFlags TestMaxHeapSizeTools * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/gc/arguments/TestSerialHeapSizeFlags.java b/hotspot/test/gc/arguments/TestSerialHeapSizeFlags.java index 0313da53aac..4e568268edd 100644 --- a/hotspot/test/gc/arguments/TestSerialHeapSizeFlags.java +++ b/hotspot/test/gc/arguments/TestSerialHeapSizeFlags.java @@ -26,7 +26,7 @@ * @key gc * @bug 8006088 * @summary Tests argument processing for initial and maximum heap size for the Serial collector - * @library /testlibrary /testlibrary/whitebox + * @library /testlibrary /../../test/lib * @build TestSerialHeapSizeFlags TestMaxHeapSizeTools * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/gc/arguments/TestSurvivorAlignmentInBytesOption.java b/hotspot/test/gc/arguments/TestSurvivorAlignmentInBytesOption.java index 4dc7845ecee..3841bfb9fde 100644 --- a/hotspot/test/gc/arguments/TestSurvivorAlignmentInBytesOption.java +++ b/hotspot/test/gc/arguments/TestSurvivorAlignmentInBytesOption.java @@ -22,29 +22,24 @@ */ import com.oracle.java.testlibrary.ExitCode; -import com.oracle.java.testlibrary.Utils; import com.oracle.java.testlibrary.cli.CommandLineOptionTest; -import java.util.Collections; -import java.util.LinkedList; -import java.util.List; - /** * @test * @bug 8031323 * @summary Verify SurvivorAlignmentInBytes option processing. * @library /testlibrary + * @requires vm.opt.SurvivorAlignmentInBytes == null + * & vm.opt.ObjectAlignmentInBytes == null + * & vm.opt.UnlockExperimentalVMOptions == null + * & (vm.opt.IgnoreUnrecognizedVMOptions == null + * | vm.opt.IgnoreUnrecognizedVMOptions == "false") * @run main TestSurvivorAlignmentInBytesOption */ public class TestSurvivorAlignmentInBytesOption { - private static final String[] FILTERED_VM_OPTIONS - = Utils.getFilteredTestJavaOpts( - "UnlockExperimentalVMOptions", - "SurvivorAlignmentInBytes", - "ObjectAlignmentInBytes"); - public static void main(String args[]) throws Throwable { String optionName = "SurvivorAlignmentInBytes"; + String unlockExperimentalVMOpts = "UnlockExperimentalVMOptions"; String optionIsExperimental = CommandLineOptionTest.getExperimentalOptionErrorMessage( optionName); @@ -56,65 +51,84 @@ public class TestSurvivorAlignmentInBytesOption { // Verify that without -XX:+UnlockExperimentalVMOptions usage of // SurvivorAlignmentInBytes option will cause JVM startup failure // with the warning message saying that that option is experimental. + String shouldFailMessage = String.format("JVM option '%s' is " + + "experimental.%nJVM startup should fail without " + + "-XX:+UnlockExperimentalVMOptions option", optionName); CommandLineOptionTest.verifyJVMStartup( - new String[]{optionIsExperimental}, null, ExitCode.FAIL, false, - TestSurvivorAlignmentInBytesOption.prepareOptions( - "-XX:-UnlockExperimentalVMOptions", - CommandLineOptionTest.prepareNumericFlag( - optionName, 64))); + new String[]{optionIsExperimental}, null, + shouldFailMessage, shouldFailMessage, + ExitCode.FAIL, false, + "-XX:-UnlockExperimentalVMOptions", + CommandLineOptionTest.prepareBooleanFlag( + unlockExperimentalVMOpts, false), + CommandLineOptionTest.prepareNumericFlag(optionName, 64)); // Verify that with -XX:+UnlockExperimentalVMOptions passed to JVM // usage of SurvivorAlignmentInBytes option won't cause JVM startup // failure. + String shouldPassMessage = String.format("JVM option '%s' is " + + "experimental.%nJVM startup should pass with " + + "-XX:+UnlockExperimentalVMOptions option", optionName); + String noWarningMessage = "There should be no warnings when use " + + "with -XX:+UnlockExperimentalVMOptions option"; CommandLineOptionTest.verifyJVMStartup( - null, new String[]{optionIsExperimental}, ExitCode.OK, false, - TestSurvivorAlignmentInBytesOption.prepareOptions( - CommandLineOptionTest.prepareNumericFlag( - optionName, 64))); + null, new String[]{optionIsExperimental}, + shouldPassMessage, noWarningMessage, + ExitCode.OK, false, + CommandLineOptionTest.prepareBooleanFlag( + unlockExperimentalVMOpts, true), + CommandLineOptionTest.prepareNumericFlag(optionName, 64)); - // Verify that if specified SurvivorAlignmentInBytes is lower then + // Verify that if specified SurvivorAlignmentInBytes is lower than // ObjectAlignmentInBytes, then the JVM startup will fail with // appropriate error message. + shouldFailMessage = String.format("JVM startup should fail with " + + "'%s' option value lower than ObjectAlignmentInBytes", optionName); CommandLineOptionTest.verifyJVMStartup( - new String[]{valueIsTooSmall}, null, ExitCode.FAIL, false, - TestSurvivorAlignmentInBytesOption.prepareOptions( - CommandLineOptionTest.prepareNumericFlag( - optionName, 2))); + new String[]{valueIsTooSmall}, null, + shouldFailMessage, shouldFailMessage, + ExitCode.FAIL, false, + CommandLineOptionTest.prepareBooleanFlag( + unlockExperimentalVMOpts, true), + CommandLineOptionTest.prepareNumericFlag(optionName, 2)); // Verify that if specified SurvivorAlignmentInBytes value is not // a power of 2 then the JVM startup will fail with appropriate error // message. + shouldFailMessage = String.format("JVM startup should fail with " + + "'%s' option value is not a power of 2", optionName); CommandLineOptionTest.verifyJVMStartup( - new String[]{mustBePowerOf2}, null, ExitCode.FAIL, false, - TestSurvivorAlignmentInBytesOption.prepareOptions( - CommandLineOptionTest.prepareNumericFlag( - optionName, 127))); + new String[]{mustBePowerOf2}, null, + shouldFailMessage, shouldFailMessage, + ExitCode.FAIL, false, + CommandLineOptionTest.prepareBooleanFlag( + unlockExperimentalVMOpts, true), + CommandLineOptionTest.prepareNumericFlag(optionName, 127)); // Verify that if SurvivorAlignmentInBytes has correct value, then // the JVM will be started without errors. + shouldPassMessage = String.format("JVM startup should pass with " + + "correct '%s' option value", optionName); + noWarningMessage = String.format("There should be no warnings when use " + + "correct '%s' option value", optionName); CommandLineOptionTest.verifyJVMStartup( null, new String[]{".*SurvivorAlignmentInBytes.*"}, + shouldPassMessage, noWarningMessage, ExitCode.OK, false, - TestSurvivorAlignmentInBytesOption.prepareOptions( - CommandLineOptionTest.prepareNumericFlag( - optionName, 128))); + CommandLineOptionTest.prepareBooleanFlag( + unlockExperimentalVMOpts, true), + CommandLineOptionTest.prepareNumericFlag(optionName, 128)); // Verify that we can setup different SurvivorAlignmentInBytes values. for (int alignment = 32; alignment <= 128; alignment *= 2) { + shouldPassMessage = String.format("JVM startup should pass with " + + "'%s' = %d", optionName, alignment); CommandLineOptionTest.verifyOptionValue(optionName, - Integer.toString(alignment), false, - TestSurvivorAlignmentInBytesOption.prepareOptions( - CommandLineOptionTest.prepareNumericFlag( - optionName, alignment))); + Integer.toString(alignment), shouldPassMessage, + CommandLineOptionTest.prepareBooleanFlag( + unlockExperimentalVMOpts, true), + CommandLineOptionTest.prepareNumericFlag( + optionName, alignment)); } } - - private static String[] prepareOptions(String... options) { - List finalOptions = new LinkedList<>(); - Collections.addAll(finalOptions, - TestSurvivorAlignmentInBytesOption.FILTERED_VM_OPTIONS); - finalOptions.add(CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS); - Collections.addAll(finalOptions, options); - return finalOptions.toArray(new String[finalOptions.size()]); - } } diff --git a/hotspot/test/gc/arguments/TestUseCompressedOopsErgo.java b/hotspot/test/gc/arguments/TestUseCompressedOopsErgo.java index 0dd5739e835..09a54a0a790 100644 --- a/hotspot/test/gc/arguments/TestUseCompressedOopsErgo.java +++ b/hotspot/test/gc/arguments/TestUseCompressedOopsErgo.java @@ -26,7 +26,7 @@ * @key gc * @bug 8010722 * @summary Tests ergonomics for UseCompressedOops. - * @library /testlibrary /testlibrary/whitebox + * @library /testlibrary /../../test/lib * @build TestUseCompressedOopsErgo TestUseCompressedOopsErgoTools * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/gc/class_unloading/TestCMSClassUnloadingEnabledHWM.java b/hotspot/test/gc/class_unloading/TestCMSClassUnloadingEnabledHWM.java index 0e33bcf967d..c7985dfd47d 100644 --- a/hotspot/test/gc/class_unloading/TestCMSClassUnloadingEnabledHWM.java +++ b/hotspot/test/gc/class_unloading/TestCMSClassUnloadingEnabledHWM.java @@ -25,7 +25,7 @@ * @test * @key gc * @bug 8049831 - * @library /testlibrary /testlibrary/whitebox + * @library /testlibrary /../../test/lib * @build TestCMSClassUnloadingEnabledHWM * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/gc/class_unloading/TestG1ClassUnloadingHWM.java b/hotspot/test/gc/class_unloading/TestG1ClassUnloadingHWM.java index 7a2ebc18b42..374184e3944 100644 --- a/hotspot/test/gc/class_unloading/TestG1ClassUnloadingHWM.java +++ b/hotspot/test/gc/class_unloading/TestG1ClassUnloadingHWM.java @@ -25,7 +25,7 @@ * @test * @key gc * @bug 8049831 - * @library /testlibrary /testlibrary/whitebox + * @library /testlibrary /../../test/lib * @build TestG1ClassUnloadingHWM * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/gc/g1/TestHumongousCodeCacheRoots.java b/hotspot/test/gc/g1/TestHumongousCodeCacheRoots.java index d234cf81dfb..c4a81e2d5f0 100644 --- a/hotspot/test/gc/g1/TestHumongousCodeCacheRoots.java +++ b/hotspot/test/gc/g1/TestHumongousCodeCacheRoots.java @@ -26,7 +26,7 @@ * @key regression * @key gc * @bug 8027756 - * @library /testlibrary /testlibrary/whitebox + * @library /testlibrary /../../test/lib * @build TestHumongousCodeCacheRoots * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/gc/g1/TestShrinkAuxiliaryData00.java b/hotspot/test/gc/g1/TestShrinkAuxiliaryData00.java index 4395bb2d71c..7d36e821048 100644 --- a/hotspot/test/gc/g1/TestShrinkAuxiliaryData00.java +++ b/hotspot/test/gc/g1/TestShrinkAuxiliaryData00.java @@ -26,7 +26,7 @@ * @bug 8038423 * @summary Checks that decommitment occurs for JVM with different * G1ConcRSLogCacheSize and ObjectAlignmentInBytes options values - * @library /testlibrary /testlibrary/whitebox + * @library /testlibrary /../../test/lib * @build TestShrinkAuxiliaryData TestShrinkAuxiliaryData00 * @run driver/timeout=720 TestShrinkAuxiliaryData00 */ diff --git a/hotspot/test/gc/g1/TestShrinkAuxiliaryData05.java b/hotspot/test/gc/g1/TestShrinkAuxiliaryData05.java index f7ff497cb9b..403b7bfe5aa 100644 --- a/hotspot/test/gc/g1/TestShrinkAuxiliaryData05.java +++ b/hotspot/test/gc/g1/TestShrinkAuxiliaryData05.java @@ -27,7 +27,7 @@ * @summary Checks that decommitment occurs for JVM with different * G1ConcRSLogCacheSize and ObjectAlignmentInBytes options values * @requires vm.gc=="G1" | vm.gc=="null" - * @library /testlibrary /testlibrary/whitebox + * @library /testlibrary /../../test/lib * @build TestShrinkAuxiliaryData TestShrinkAuxiliaryData05 * @run driver/timeout=720 TestShrinkAuxiliaryData05 */ diff --git a/hotspot/test/gc/g1/TestShrinkAuxiliaryData10.java b/hotspot/test/gc/g1/TestShrinkAuxiliaryData10.java index 0f1cf9b07e9..ad2ab4155b8 100644 --- a/hotspot/test/gc/g1/TestShrinkAuxiliaryData10.java +++ b/hotspot/test/gc/g1/TestShrinkAuxiliaryData10.java @@ -27,7 +27,7 @@ * @summary Checks that decommitment occurs for JVM with different * G1ConcRSLogCacheSize and ObjectAlignmentInBytes options values * @requires vm.gc=="G1" | vm.gc=="null" - * @library /testlibrary /testlibrary/whitebox + * @library /testlibrary /../../test/lib * @build TestShrinkAuxiliaryData TestShrinkAuxiliaryData10 * @run driver/timeout=720 TestShrinkAuxiliaryData10 */ diff --git a/hotspot/test/gc/g1/TestShrinkAuxiliaryData15.java b/hotspot/test/gc/g1/TestShrinkAuxiliaryData15.java index 33a0ecb94dc..76d54ae67e9 100644 --- a/hotspot/test/gc/g1/TestShrinkAuxiliaryData15.java +++ b/hotspot/test/gc/g1/TestShrinkAuxiliaryData15.java @@ -27,7 +27,7 @@ * @summary Checks that decommitment occurs for JVM with different * G1ConcRSLogCacheSize and ObjectAlignmentInBytes options values * @requires vm.gc=="G1" | vm.gc=="null" - * @library /testlibrary /testlibrary/whitebox + * @library /testlibrary /../../test/lib * @build TestShrinkAuxiliaryData TestShrinkAuxiliaryData15 * @run driver/timeout=720 TestShrinkAuxiliaryData15 */ diff --git a/hotspot/test/gc/g1/TestShrinkAuxiliaryData20.java b/hotspot/test/gc/g1/TestShrinkAuxiliaryData20.java index 236a4f1ca6d..43c349e6c63 100644 --- a/hotspot/test/gc/g1/TestShrinkAuxiliaryData20.java +++ b/hotspot/test/gc/g1/TestShrinkAuxiliaryData20.java @@ -27,7 +27,7 @@ * @summary Checks that decommitment occurs for JVM with different * G1ConcRSLogCacheSize and ObjectAlignmentInBytes options values * @requires vm.gc=="G1" | vm.gc=="null" - * @library /testlibrary /testlibrary/whitebox + * @library /testlibrary /../../test/lib * @build TestShrinkAuxiliaryData TestShrinkAuxiliaryData20 * @run driver/timeout=720 TestShrinkAuxiliaryData20 */ diff --git a/hotspot/test/gc/g1/TestShrinkAuxiliaryData25.java b/hotspot/test/gc/g1/TestShrinkAuxiliaryData25.java index 7defc9522f3..e86d75a20ee 100644 --- a/hotspot/test/gc/g1/TestShrinkAuxiliaryData25.java +++ b/hotspot/test/gc/g1/TestShrinkAuxiliaryData25.java @@ -27,7 +27,7 @@ * @summary Checks that decommitment occurs for JVM with different * G1ConcRSLogCacheSize and ObjectAlignmentInBytes options values * @requires vm.gc=="G1" | vm.gc=="null" - * @library /testlibrary /testlibrary/whitebox + * @library /testlibrary /../../test/lib * @build TestShrinkAuxiliaryData TestShrinkAuxiliaryData25 * @run driver/timeout=720 TestShrinkAuxiliaryData25 */ diff --git a/hotspot/test/gc/g1/TestShrinkAuxiliaryData30.java b/hotspot/test/gc/g1/TestShrinkAuxiliaryData30.java index b51ec8449d8..08904841ad9 100644 --- a/hotspot/test/gc/g1/TestShrinkAuxiliaryData30.java +++ b/hotspot/test/gc/g1/TestShrinkAuxiliaryData30.java @@ -27,7 +27,7 @@ * @summary Checks that decommitment occurs for JVM with different * G1ConcRSLogCacheSize and ObjectAlignmentInBytes options values * @requires vm.gc=="G1" | vm.gc=="null" - * @library /testlibrary /testlibrary/whitebox + * @library /testlibrary /../../test/lib * @build TestShrinkAuxiliaryData TestShrinkAuxiliaryData30 * @run driver/timeout=720 TestShrinkAuxiliaryData30 */ diff --git a/hotspot/test/gc/metaspace/TestCapacityUntilGCWrapAround.java b/hotspot/test/gc/metaspace/TestCapacityUntilGCWrapAround.java index 600e70745bf..a95d6f072d6 100644 --- a/hotspot/test/gc/metaspace/TestCapacityUntilGCWrapAround.java +++ b/hotspot/test/gc/metaspace/TestCapacityUntilGCWrapAround.java @@ -25,7 +25,7 @@ * @test * @key gc * @bug 8049831 - * @library /testlibrary /testlibrary/whitebox + * @library /testlibrary /../../test/lib * @build TestCapacityUntilGCWrapAround * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/gc/survivorAlignment/TestAllocationInEden.java b/hotspot/test/gc/survivorAlignment/TestAllocationInEden.java index f5572386fdf..61f0c482047 100644 --- a/hotspot/test/gc/survivorAlignment/TestAllocationInEden.java +++ b/hotspot/test/gc/survivorAlignment/TestAllocationInEden.java @@ -26,7 +26,7 @@ * @bug 8031323 * @summary Verify that object's alignment in eden space is not affected by * SurvivorAlignmentInBytes option. - * @library /testlibrary /testlibrary/whitebox + * @library /testlibrary /../../test/lib * @build TestAllocationInEden SurvivorAlignmentTestMain AlignmentHelper * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission @@ -34,37 +34,43 @@ * -XX:+WhiteBoxAPI -XX:NewSize=64m -XX:MaxNewSize=64m * -XX:SurvivorRatio=1 -XX:+UnlockExperimentalVMOptions * -XX:SurvivorAlignmentInBytes=32 -XX:-UseTLAB - * -XX:OldSize=128m -XX:-ExplicitGCInvokesConcurrent + * -XX:OldSize=128m -XX:MaxHeapSize=192m + * -XX:-ExplicitGCInvokesConcurrent * TestAllocationInEden 10m 9 EDEN * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+WhiteBoxAPI -XX:NewSize=64m -XX:MaxNewSize=64m * -XX:SurvivorRatio=1 -XX:+UnlockExperimentalVMOptions * -XX:SurvivorAlignmentInBytes=32 -XX:-UseTLAB - * -XX:OldSize=128m -XX:-ExplicitGCInvokesConcurrent + * -XX:OldSize=128m -XX:MaxHeapSize=192m + * -XX:-ExplicitGCInvokesConcurrent * TestAllocationInEden 10m 47 EDEN * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+WhiteBoxAPI -XX:NewSize=64m -XX:MaxNewSize=64m * -XX:SurvivorRatio=1 -XX:+UnlockExperimentalVMOptions * -XX:SurvivorAlignmentInBytes=64 -XX:-UseTLAB - * -XX:OldSize=128m -XX:-ExplicitGCInvokesConcurrent + * -XX:OldSize=128m -XX:MaxHeapSize=192m + * -XX:-ExplicitGCInvokesConcurrent * TestAllocationInEden 10m 9 EDEN * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+WhiteBoxAPI -XX:NewSize=64m -XX:MaxNewSize=64m * -XX:SurvivorRatio=1 -XX:+UnlockExperimentalVMOptions * -XX:SurvivorAlignmentInBytes=64 -XX:-UseTLAB - * -XX:OldSize=128m -XX:-ExplicitGCInvokesConcurrent + * -XX:OldSize=128m -XX:MaxHeapSize=192m + * -XX:-ExplicitGCInvokesConcurrent * TestAllocationInEden 10m 87 EDEN * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+WhiteBoxAPI -XX:NewSize=64m -XX:MaxNewSize=64m * -XX:SurvivorRatio=1 -XX:+UnlockExperimentalVMOptions * -XX:SurvivorAlignmentInBytes=128 -XX:-UseTLAB - * -XX:OldSize=128m -XX:-ExplicitGCInvokesConcurrent + * -XX:OldSize=128m -XX:MaxHeapSize=192m + * -XX:-ExplicitGCInvokesConcurrent * TestAllocationInEden 10m 9 EDEN * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+WhiteBoxAPI -XX:NewSize=64m -XX:MaxNewSize=64m * -XX:SurvivorRatio=1 -XX:+UnlockExperimentalVMOptions * -XX:SurvivorAlignmentInBytes=128 -XX:-UseTLAB - * -XX:OldSize=128m -XX:-ExplicitGCInvokesConcurrent + * -XX:OldSize=128m -XX:MaxHeapSize=192m + * -XX:-ExplicitGCInvokesConcurrent * TestAllocationInEden 10m 147 EDEN */ public class TestAllocationInEden { diff --git a/hotspot/test/gc/survivorAlignment/TestPromotionFromEdenToTenured.java b/hotspot/test/gc/survivorAlignment/TestPromotionFromEdenToTenured.java index e5025f75c5a..d72e78cbcec 100644 --- a/hotspot/test/gc/survivorAlignment/TestPromotionFromEdenToTenured.java +++ b/hotspot/test/gc/survivorAlignment/TestPromotionFromEdenToTenured.java @@ -26,50 +26,50 @@ * @bug 8031323 * @summary Verify that objects promoted from eden space to tenured space during * full GC are not aligned to SurvivorAlignmentInBytes value. - * @library /testlibrary /testlibrary/whitebox + * @library /testlibrary /../../test/lib * @build TestPromotionFromEdenToTenured SurvivorAlignmentTestMain * AlignmentHelper * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+WhiteBoxAPI -XX:NewSize=64m -XX:MaxNewSize=64m - * -XX:OldSize=32m -XX:SurvivorRatio=1 - * -XX:-ExplicitGCInvokesConcurrent + * -XX:OldSize=32m -XX:MaxHeapSize=96m -XX:SurvivorRatio=1 + * -XX:-ExplicitGCInvokesConcurrent * -XX:+UnlockExperimentalVMOptions * -XX:SurvivorAlignmentInBytes=32 * TestPromotionFromEdenToTenured 10m 9 TENURED * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+WhiteBoxAPI -XX:NewSize=64m -XX:MaxNewSize=64m - * -XX:OldSize=32m -XX:SurvivorRatio=1 - * -XX:-ExplicitGCInvokesConcurrent + * -XX:OldSize=32m -XX:MaxHeapSize=96m -XX:SurvivorRatio=1 + * -XX:-ExplicitGCInvokesConcurrent * -XX:+UnlockExperimentalVMOptions * -XX:SurvivorAlignmentInBytes=32 * TestPromotionFromEdenToTenured 10m 47 TENURED * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+WhiteBoxAPI -XX:NewSize=64m -XX:MaxNewSize=64m - * -XX:OldSize=32m -XX:SurvivorRatio=1 - * -XX:-ExplicitGCInvokesConcurrent + * -XX:OldSize=32m -XX:MaxHeapSize=96m + * -XX:SurvivorRatio=1 -XX:-ExplicitGCInvokesConcurrent * -XX:+UnlockExperimentalVMOptions * -XX:SurvivorAlignmentInBytes=64 * TestPromotionFromEdenToTenured 10m 9 TENURED * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+WhiteBoxAPI -XX:NewSize=64m -XX:MaxNewSize=64m - * -XX:OldSize=32m -XX:SurvivorRatio=1 - * -XX:-ExplicitGCInvokesConcurrent + * -XX:OldSize=32m -XX:MaxHeapSize=128m + * -XX:SurvivorRatio=1 -XX:-ExplicitGCInvokesConcurrent * -XX:+UnlockExperimentalVMOptions * -XX:SurvivorAlignmentInBytes=64 * TestPromotionFromEdenToTenured 10m 87 TENURED * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+WhiteBoxAPI -XX:NewSize=64m -XX:MaxNewSize=64m - * -XX:OldSize=32M -XX:SurvivorRatio=1 - * -XX:-ExplicitGCInvokesConcurrent + * -XX:OldSize=32M -XX:MaxHeapSize=96m -XX:SurvivorRatio=1 + * -XX:-ExplicitGCInvokesConcurrent * -XX:+UnlockExperimentalVMOptions * -XX:SurvivorAlignmentInBytes=128 * TestPromotionFromEdenToTenured 10m 9 TENURED * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+WhiteBoxAPI -XX:NewSize=64m -XX:MaxNewSize=64m - * -XX:OldSize=32m -XX:SurvivorRatio=1 - * -XX:-ExplicitGCInvokesConcurrent + * -XX:OldSize=32m -XX:MaxHeapSize=96m -XX:SurvivorRatio=1 + * -XX:-ExplicitGCInvokesConcurrent * -XX:+UnlockExperimentalVMOptions * -XX:SurvivorAlignmentInBytes=128 * TestPromotionFromEdenToTenured 10m 147 TENURED diff --git a/hotspot/test/gc/survivorAlignment/TestPromotionFromSurvivorToTenuredAfterFullGC.java b/hotspot/test/gc/survivorAlignment/TestPromotionFromSurvivorToTenuredAfterFullGC.java index 960ef28ee91..da496c03744 100644 --- a/hotspot/test/gc/survivorAlignment/TestPromotionFromSurvivorToTenuredAfterFullGC.java +++ b/hotspot/test/gc/survivorAlignment/TestPromotionFromSurvivorToTenuredAfterFullGC.java @@ -26,44 +26,44 @@ * @bug 8031323 * @summary Verify that objects promoted from survivor space to tenured space * during full GC are not aligned to SurvivorAlignmentInBytes value. - * @library /testlibrary /testlibrary/whitebox + * @library /testlibrary /../../test/lib * @build TestPromotionFromSurvivorToTenuredAfterFullGC * SurvivorAlignmentTestMain AlignmentHelper * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+WhiteBoxAPI -XX:NewSize=128m -XX:MaxNewSize=128m - * -XX:OldSize=32m -XX:SurvivorRatio=1 - * -XX:-ExplicitGCInvokesConcurrent + * -XX:OldSize=32m -XX:MaxHeapSize=160m + * -XX:SurvivorRatio=1 -XX:-ExplicitGCInvokesConcurrent * -XX:+UnlockExperimentalVMOptions * -XX:SurvivorAlignmentInBytes=32 * TestPromotionFromSurvivorToTenuredAfterFullGC 10m 9 TENURED * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+WhiteBoxAPI -XX:NewSize=128m -XX:MaxNewSize=128m - * -XX:OldSize=32m -XX:SurvivorRatio=1 - * -XX:-ExplicitGCInvokesConcurrent + * -XX:OldSize=32m -XX:MaxHeapSize=160m + * -XX:SurvivorRatio=1 -XX:-ExplicitGCInvokesConcurrent * -XX:+UnlockExperimentalVMOptions * -XX:SurvivorAlignmentInBytes=32 * TestPromotionFromSurvivorToTenuredAfterFullGC 20m 47 * TENURED * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+WhiteBoxAPI -XX:NewSize=200m -XX:MaxNewSize=200m - * -XX:OldSize=32m -XX:InitialHeapSize=232m + * -XX:OldSize=32m -XX:MaxHeapSize=232m * -XX:SurvivorRatio=1 -XX:-ExplicitGCInvokesConcurrent * -XX:+UnlockExperimentalVMOptions * -XX:SurvivorAlignmentInBytes=64 * TestPromotionFromSurvivorToTenuredAfterFullGC 10m 9 TENURED * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+WhiteBoxAPI -XX:NewSize=128m -XX:MaxNewSize=128m - * -XX:OldSize=32m -XX:SurvivorRatio=1 - * -XX:-ExplicitGCInvokesConcurrent + * -XX:OldSize=32m -XX:MaxHeapSize=160m + * -XX:SurvivorRatio=1 -XX:-ExplicitGCInvokesConcurrent * -XX:+UnlockExperimentalVMOptions * -XX:SurvivorAlignmentInBytes=64 * TestPromotionFromSurvivorToTenuredAfterFullGC 20m 87 * TENURED * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+WhiteBoxAPI -XX:NewSize=256m -XX:MaxNewSize=256m - * -XX:OldSize=32M -XX:InitialHeapSize=288m + * -XX:OldSize=32M -XX:MaxHeapSize=288m * -XX:SurvivorRatio=1 -XX:-ExplicitGCInvokesConcurrent * -XX:+UnlockExperimentalVMOptions * -XX:SurvivorAlignmentInBytes=128 @@ -71,8 +71,8 @@ * TENURED * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+WhiteBoxAPI -XX:NewSize=128m -XX:MaxNewSize=128m - * -XX:OldSize=32m -XX:SurvivorRatio=1 - * -XX:-ExplicitGCInvokesConcurrent + * -XX:OldSize=32m -XX:MaxHeapSize=160m + * -XX:SurvivorRatio=1 -XX:-ExplicitGCInvokesConcurrent * -XX:+UnlockExperimentalVMOptions * -XX:SurvivorAlignmentInBytes=128 * TestPromotionFromSurvivorToTenuredAfterFullGC 20m 147 diff --git a/hotspot/test/gc/survivorAlignment/TestPromotionFromSurvivorToTenuredAfterMinorGC.java b/hotspot/test/gc/survivorAlignment/TestPromotionFromSurvivorToTenuredAfterMinorGC.java index 3b2dacd727c..754349c9b43 100644 --- a/hotspot/test/gc/survivorAlignment/TestPromotionFromSurvivorToTenuredAfterMinorGC.java +++ b/hotspot/test/gc/survivorAlignment/TestPromotionFromSurvivorToTenuredAfterMinorGC.java @@ -27,14 +27,14 @@ * @summary Verify that objects promoted from survivor space to tenured space * when their age exceeded tenuring threshold are not aligned to * SurvivorAlignmentInBytes value. - * @library /testlibrary /testlibrary/whitebox + * @library /testlibrary /../../test/lib * @build TestPromotionFromSurvivorToTenuredAfterMinorGC * SurvivorAlignmentTestMain AlignmentHelper * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+WhiteBoxAPI -XX:NewSize=128m -XX:MaxNewSize=128m - * -XX:OldSize=32M -XX:SurvivorRatio=1 + * -XX:OldSize=32M -XX:MaxHeapSize=160m -XX:SurvivorRatio=1 * -XX:-ExplicitGCInvokesConcurrent * -XX:+UnlockExperimentalVMOptions * -XX:SurvivorAlignmentInBytes=32 @@ -42,7 +42,7 @@ * TENURED * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+WhiteBoxAPI -XX:NewSize=128m -XX:MaxNewSize=128m - * -XX:OldSize=32M -XX:SurvivorRatio=1 + * -XX:OldSize=32M -XX:MaxHeapSize=160m -XX:SurvivorRatio=1 * -XX:-ExplicitGCInvokesConcurrent * -XX:+UnlockExperimentalVMOptions * -XX:SurvivorAlignmentInBytes=32 @@ -50,15 +50,15 @@ * TENURED * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+WhiteBoxAPI -XX:NewSize=200m -XX:MaxNewSize=200m - * -XX:OldSize=32M -XX:InitialHeapSize=232m - * -XX:SurvivorRatio=1 -XX:-ExplicitGCInvokesConcurrent + * -XX:OldSize=32M -XX:MaxHeapSize=232m -XX:SurvivorRatio=1 + * -XX:-ExplicitGCInvokesConcurrent * -XX:+UnlockExperimentalVMOptions * -XX:SurvivorAlignmentInBytes=64 * TestPromotionFromSurvivorToTenuredAfterMinorGC 10m 9 * TENURED * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+WhiteBoxAPI -XX:NewSize=128m -XX:MaxNewSize=128m - * -XX:OldSize=32M -XX:SurvivorRatio=1 + * -XX:OldSize=32M -XX:MaxHeapSize=160m -XX:SurvivorRatio=1 * -XX:-ExplicitGCInvokesConcurrent * -XX:+UnlockExperimentalVMOptions * -XX:SurvivorAlignmentInBytes=64 @@ -66,15 +66,15 @@ * TENURED * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+WhiteBoxAPI -XX:NewSize=256m -XX:MaxNewSize=256m - * -XX:OldSize=32M -XX:InitialHeapSize=288m - * -XX:SurvivorRatio=1 -XX:-ExplicitGCInvokesConcurrent + * -XX:OldSize=32M -XX:MaxHeapSize=288m -XX:SurvivorRatio=1 + * -XX:-ExplicitGCInvokesConcurrent * -XX:+UnlockExperimentalVMOptions * -XX:SurvivorAlignmentInBytes=128 * TestPromotionFromSurvivorToTenuredAfterMinorGC 10m 9 * TENURED * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+WhiteBoxAPI -XX:NewSize=128m -XX:MaxNewSize=128m - * -XX:OldSize=32M -XX:SurvivorRatio=1 + * -XX:OldSize=32M -XX:MaxHeapSize=160m -XX:SurvivorRatio=1 * -XX:-ExplicitGCInvokesConcurrent * -XX:+UnlockExperimentalVMOptions * -XX:SurvivorAlignmentInBytes=128 diff --git a/hotspot/test/gc/survivorAlignment/TestPromotionToSurvivor.java b/hotspot/test/gc/survivorAlignment/TestPromotionToSurvivor.java index 59087f6b0e5..20407c217ef 100644 --- a/hotspot/test/gc/survivorAlignment/TestPromotionToSurvivor.java +++ b/hotspot/test/gc/survivorAlignment/TestPromotionToSurvivor.java @@ -26,7 +26,7 @@ * @bug 8031323 * @summary Verify that objects promoted from eden space to survivor space after * minor GC are aligned to SurvivorAlignmentInBytes. - * @library /testlibrary /testlibrary/whitebox + * @library /testlibrary /../../test/lib * @build TestPromotionToSurvivor * SurvivorAlignmentTestMain AlignmentHelper * @run main ClassFileInstaller sun.hotspot.WhiteBox @@ -35,36 +35,37 @@ * -XX:+WhiteBoxAPI -XX:NewSize=128m -XX:MaxNewSize=128m * -XX:SurvivorRatio=1 -XX:+UnlockExperimentalVMOptions * -XX:SurvivorAlignmentInBytes=32 -XX:OldSize=128m - * -XX:-ExplicitGCInvokesConcurrent + * -XX:MaxHeapSize=256m -XX:-ExplicitGCInvokesConcurrent * TestPromotionToSurvivor 10m 9 SURVIVOR * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+WhiteBoxAPI -XX:NewSize=128m -XX:MaxNewSize=128m * -XX:SurvivorRatio=1 -XX:+UnlockExperimentalVMOptions * -XX:SurvivorAlignmentInBytes=32 -XX:OldSize=128m + * -XX:MaxHeapSize=256m -XX:-ExplicitGCInvokesConcurrent * TestPromotionToSurvivor 20m 47 SURVIVOR * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+WhiteBoxAPI -XX:NewSize=128m -XX:MaxNewSize=128m * -XX:SurvivorRatio=1 -XX:+UnlockExperimentalVMOptions * -XX:SurvivorAlignmentInBytes=64 -XX:OldSize=128m - * -XX:-ExplicitGCInvokesConcurrent + * -XX:MaxHeapSize=256m -XX:-ExplicitGCInvokesConcurrent * TestPromotionToSurvivor 8m 9 SURVIVOR * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+WhiteBoxAPI -XX:NewSize=128m -XX:MaxNewSize=128m * -XX:SurvivorRatio=1 -XX:+UnlockExperimentalVMOptions * -XX:SurvivorAlignmentInBytes=64 -XX:OldSize=128m - * -XX:-ExplicitGCInvokesConcurrent + * -XX:MaxHeapSize=256m -XX:-ExplicitGCInvokesConcurrent * TestPromotionToSurvivor 20m 87 SURVIVOR * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+WhiteBoxAPI -XX:NewSize=256m -XX:MaxNewSize=256m * -XX:SurvivorRatio=1 -XX:+UnlockExperimentalVMOptions - * -XX:SurvivorAlignmentInBytes=128 -XX:OldSize=32m - * -XX:InitialHeapSize=288m -XX:-ExplicitGCInvokesConcurrent + * -XX:SurvivorAlignmentInBytes=128 -XX:OldSize=128m + * -XX:MaxHeapSize=384m -XX:-ExplicitGCInvokesConcurrent * TestPromotionToSurvivor 10m 9 SURVIVOR * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+WhiteBoxAPI -XX:NewSize=128m -XX:MaxNewSize=128m * -XX:SurvivorRatio=1 -XX:+UnlockExperimentalVMOptions * -XX:SurvivorAlignmentInBytes=128 -XX:OldSize=128m - * -XX:-ExplicitGCInvokesConcurrent + * -XX:MaxHeapSize=256m -XX:-ExplicitGCInvokesConcurrent * TestPromotionToSurvivor 20m 147 SURVIVOR */ public class TestPromotionToSurvivor { diff --git a/hotspot/test/gc/whitebox/TestConcMarkCycleWB.java b/hotspot/test/gc/whitebox/TestConcMarkCycleWB.java index 2d97bc739c6..e7a048309be 100644 --- a/hotspot/test/gc/whitebox/TestConcMarkCycleWB.java +++ b/hotspot/test/gc/whitebox/TestConcMarkCycleWB.java @@ -25,7 +25,7 @@ * @test TestConMarkCycleWB * @bug 8065579 * @requires vm.gc=="null" | vm.gc=="G1" - * @library /testlibrary /testlibrary/whitebox + * @library /testlibrary /../../test/lib * @build ClassFileInstaller com.oracle.java.testlibrary.* sun.hotspot.WhiteBox TestConcMarkCycleWB * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/gc/whitebox/TestWBGC.java b/hotspot/test/gc/whitebox/TestWBGC.java index 8cdb74b326b..e10474ad4e7 100644 --- a/hotspot/test/gc/whitebox/TestWBGC.java +++ b/hotspot/test/gc/whitebox/TestWBGC.java @@ -25,7 +25,7 @@ * @test TestWBGC * @bug 8055098 * @summary Test verify that WB methods isObjectInOldGen and youngGC works correctly. - * @library /testlibrary /testlibrary/whitebox + * @library /testlibrary /../../test/lib * @build TestWBGC * @run main ClassFileInstaller sun.hotspot.WhiteBox * @run driver TestWBGC diff --git a/hotspot/test/runtime/ClassUnload/KeepAliveClass.java b/hotspot/test/runtime/ClassUnload/KeepAliveClass.java index 4b9d9e41e02..8bac5b7a464 100644 --- a/hotspot/test/runtime/ClassUnload/KeepAliveClass.java +++ b/hotspot/test/runtime/ClassUnload/KeepAliveClass.java @@ -24,7 +24,7 @@ /* * @test KeepAliveClass * @summary This test case uses a java.lang.Class instance to keep a class alive. - * @library /testlibrary /testlibrary/whitebox /runtime/testlibrary + * @library /testlibrary /../../test/lib /runtime/testlibrary * @library classes * @build KeepAliveClass test.Empty * @build ClassUnloadCommon diff --git a/hotspot/test/runtime/ClassUnload/KeepAliveClassLoader.java b/hotspot/test/runtime/ClassUnload/KeepAliveClassLoader.java index 3b1f814f7f8..5bd4431f046 100644 --- a/hotspot/test/runtime/ClassUnload/KeepAliveClassLoader.java +++ b/hotspot/test/runtime/ClassUnload/KeepAliveClassLoader.java @@ -24,7 +24,7 @@ /* * @test KeepAliveClassLoader * @summary This test case uses a java.lang.ClassLoader instance to keep a class alive. - * @library /testlibrary /testlibrary/whitebox /runtime/testlibrary + * @library /testlibrary /../../test/lib /runtime/testlibrary * @library classes * @build KeepAliveClassLoader test.Empty * @build ClassUnloadCommon diff --git a/hotspot/test/runtime/ClassUnload/KeepAliveObject.java b/hotspot/test/runtime/ClassUnload/KeepAliveObject.java index 8c46a0be4cf..1e4126cb5ff 100644 --- a/hotspot/test/runtime/ClassUnload/KeepAliveObject.java +++ b/hotspot/test/runtime/ClassUnload/KeepAliveObject.java @@ -24,7 +24,7 @@ /* * @test KeepAliveObject * @summary This test case uses a class instance to keep the class alive. - * @library /testlibrary /testlibrary/whitebox /runtime/testlibrary + * @library /testlibrary /../../test/lib /runtime/testlibrary * @library classes * @build KeepAliveObject test.Empty * @build ClassUnloadCommon diff --git a/hotspot/test/runtime/ClassUnload/KeepAliveSoftReference.java b/hotspot/test/runtime/ClassUnload/KeepAliveSoftReference.java index 80258dc4ed1..ae261768149 100644 --- a/hotspot/test/runtime/ClassUnload/KeepAliveSoftReference.java +++ b/hotspot/test/runtime/ClassUnload/KeepAliveSoftReference.java @@ -24,7 +24,7 @@ /* * @test KeepAliveSoftReference * @summary This test case uses a java.lang.ref.SoftReference referencing a class instance to keep a class alive. - * @library /testlibrary /testlibrary/whitebox /runtime/testlibrary + * @library /testlibrary /../../test/lib /runtime/testlibrary * @library classes * @build KeepAliveSoftReference test.Empty * @build ClassUnloadCommon diff --git a/hotspot/test/runtime/ClassUnload/UnloadTest.java b/hotspot/test/runtime/ClassUnload/UnloadTest.java index 6398a077a17..452155e3e2c 100644 --- a/hotspot/test/runtime/ClassUnload/UnloadTest.java +++ b/hotspot/test/runtime/ClassUnload/UnloadTest.java @@ -23,7 +23,7 @@ /* * @test UnloadTest - * @library /runtime/testlibrary /testlibrary /testlibrary/whitebox + * @library /runtime/testlibrary /testlibrary /../../test/lib * @library classes * @build ClassUnloadCommon test.Empty * @build UnloadTest diff --git a/hotspot/test/runtime/CommandLine/TraceExceptionsTest.java b/hotspot/test/runtime/CommandLine/TraceExceptionsTest.java index 8cba4a5bf72..f8aa86298c7 100644 --- a/hotspot/test/runtime/CommandLine/TraceExceptionsTest.java +++ b/hotspot/test/runtime/CommandLine/TraceExceptionsTest.java @@ -33,11 +33,6 @@ import com.oracle.java.testlibrary.*; public class TraceExceptionsTest { public static void main(String[] args) throws Exception { - if (!Platform.isDebugBuild()) { - System.out.println("Skip the test on product builds since XX:+TraceExceptions is not available on product builds"); - return; - } - ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( "-XX:+TraceExceptions", "NoClassFound"); OutputAnalyzer output = new OutputAnalyzer(pb.start()); diff --git a/hotspot/test/runtime/Metaspace/FragmentMetaspace.java b/hotspot/test/runtime/Metaspace/FragmentMetaspace.java index 5e1a7200493..f44bce8cfd9 100644 --- a/hotspot/test/runtime/Metaspace/FragmentMetaspace.java +++ b/hotspot/test/runtime/Metaspace/FragmentMetaspace.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -25,7 +25,7 @@ * @test * @library /runtime/testlibrary * @build GeneratedClassLoader - * @run main/othervm/timeout=200 FragmentMetaspace + * @run main/othervm/timeout=200 -Xmx300m FragmentMetaspace */ import java.io.IOException; @@ -38,25 +38,34 @@ import java.io.IOException; */ public class FragmentMetaspace { + public static Class c; + public static void main(String... args) { - runGrowing(Long.valueOf(System.getProperty("time", "80000"))); + runGrowing(Long.valueOf(System.getProperty("time", "80000")), + Integer.valueOf(System.getProperty("iterations", "200"))); // try to clean up and unload classes to decrease // class verification time in debug vm System.gc(); } - private static void runGrowing(long time) { + private static void runGrowing(long time, int iterations) { long startTime = System.currentTimeMillis(); - for (int i = 0; System.currentTimeMillis() < startTime + time; ++i) { + for (int i = 0; System.currentTimeMillis() < startTime + time && i < iterations; ++i) { try { GeneratedClassLoader gcl = new GeneratedClassLoader(); - Class c = gcl.getGeneratedClasses(i, 100)[0]; + // getGeneratedClasses throws a RuntimeException in cases where + // the javac exit code is not 0. If the original reason for the exception is + // a "java.lang.OutOfMemoryError: Java heap space", + // increase the heap size in the @run tag and rerun the test. + // The heap can be exhausted by this test, but heap exhaustion + // is not a failure mode of this test and should be ignored. + c = gcl.getGeneratedClasses(i, 100)[0]; c.newInstance(); c = null; gcl = null; - } catch (IOException|InstantiationException|IllegalAccessException ex) { + } catch (IOException | InstantiationException | IllegalAccessException ex) { throw new RuntimeException(ex); } } diff --git a/hotspot/test/runtime/NMT/ChangeTrackingLevel.java b/hotspot/test/runtime/NMT/ChangeTrackingLevel.java index f031c868805..2794b05a833 100644 --- a/hotspot/test/runtime/NMT/ChangeTrackingLevel.java +++ b/hotspot/test/runtime/NMT/ChangeTrackingLevel.java @@ -26,7 +26,7 @@ * @bug 8059100 * @summary Test that you can decrease NMT tracking level but not increase it. * @key nmt - * @library /testlibrary /testlibrary/whitebox + * @library /testlibrary /../../test/lib * @build ChangeTrackingLevel * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/runtime/NMT/JcmdDetailDiff.java b/hotspot/test/runtime/NMT/JcmdDetailDiff.java index 8f151c29b12..a7c6184012f 100644 --- a/hotspot/test/runtime/NMT/JcmdDetailDiff.java +++ b/hotspot/test/runtime/NMT/JcmdDetailDiff.java @@ -25,7 +25,7 @@ * @test * @summary run NMT baseline, allocate memory and verify output from detail.diff * @key nmt jcmd - * @library /testlibrary /testlibrary/whitebox + * @library /testlibrary /../../test/lib * @ignore * @build JcmdDetailDiff * @run main ClassFileInstaller sun.hotspot.WhiteBox diff --git a/hotspot/test/runtime/NMT/JcmdSummaryDiff.java b/hotspot/test/runtime/NMT/JcmdSummaryDiff.java index 93c13d7aa3c..11cb68f8fc4 100644 --- a/hotspot/test/runtime/NMT/JcmdSummaryDiff.java +++ b/hotspot/test/runtime/NMT/JcmdSummaryDiff.java @@ -25,7 +25,7 @@ * @test * @summary run NMT baseline, allocate memory and verify output from summary.diff * @key nmt jcmd - * @library /testlibrary /testlibrary/whitebox + * @library /testlibrary /../../test/lib * @build JcmdSummaryDiff * @run main ClassFileInstaller sun.hotspot.WhiteBox * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:NativeMemoryTracking=summary JcmdSummaryDiff diff --git a/hotspot/test/runtime/NMT/MallocRoundingReportTest.java b/hotspot/test/runtime/NMT/MallocRoundingReportTest.java index f0a838a3200..4827cf0fc0e 100644 --- a/hotspot/test/runtime/NMT/MallocRoundingReportTest.java +++ b/hotspot/test/runtime/NMT/MallocRoundingReportTest.java @@ -25,7 +25,7 @@ * @test * @summary Test consistency of NMT by creating allocations of the Test type with various sizes and verifying visibility with jcmd * @key nmt jcmd - * @library /testlibrary /testlibrary/whitebox + * @library /testlibrary /../../test/lib * @build MallocRoundingReportTest * @run main ClassFileInstaller sun.hotspot.WhiteBox * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:NativeMemoryTracking=detail MallocRoundingReportTest diff --git a/hotspot/test/runtime/NMT/MallocSiteHashOverflow.java b/hotspot/test/runtime/NMT/MallocSiteHashOverflow.java index 8f3404cbc42..d9a7c3ef919 100644 --- a/hotspot/test/runtime/NMT/MallocSiteHashOverflow.java +++ b/hotspot/test/runtime/NMT/MallocSiteHashOverflow.java @@ -26,7 +26,7 @@ * @summary Test corner case that overflows malloc site hashtable bucket * @requires sun.arch.data.model == "32" * @key nmt jcmd stress - * @library /testlibrary /testlibrary/whitebox + * @library /testlibrary /../../test/lib * @build MallocSiteHashOverflow * @run main ClassFileInstaller sun.hotspot.WhiteBox * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:NativeMemoryTracking=detail MallocSiteHashOverflow diff --git a/hotspot/test/runtime/NMT/MallocStressTest.java b/hotspot/test/runtime/NMT/MallocStressTest.java index 41f1ff870ea..54711517c7d 100644 --- a/hotspot/test/runtime/NMT/MallocStressTest.java +++ b/hotspot/test/runtime/NMT/MallocStressTest.java @@ -25,7 +25,7 @@ * @test * @summary Stress test for malloc tracking * @key nmt jcmd stress - * @library /testlibrary /testlibrary/whitebox + * @library /testlibrary /../../test/lib * @build MallocStressTest * @ignore - This test is disabled since it will stress NMT and timeout during normal testing * @run main ClassFileInstaller sun.hotspot.WhiteBox diff --git a/hotspot/test/runtime/NMT/MallocTestType.java b/hotspot/test/runtime/NMT/MallocTestType.java index d570c2fa6a5..614285371ca 100644 --- a/hotspot/test/runtime/NMT/MallocTestType.java +++ b/hotspot/test/runtime/NMT/MallocTestType.java @@ -25,7 +25,7 @@ * @test * @summary Test consistency of NMT by leaking a few select allocations of the Test type and then verify visibility with jcmd * @key nmt jcmd - * @library /testlibrary /testlibrary/whitebox + * @library /testlibrary /../../test/lib * @build MallocTestType * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/runtime/NMT/MallocTrackingVerify.java b/hotspot/test/runtime/NMT/MallocTrackingVerify.java index 2403a70ab9d..31c4ae76920 100644 --- a/hotspot/test/runtime/NMT/MallocTrackingVerify.java +++ b/hotspot/test/runtime/NMT/MallocTrackingVerify.java @@ -26,7 +26,7 @@ * @bug 8054836 * @summary Test to verify correctness of malloc tracking * @key nmt jcmd - * @library /testlibrary /testlibrary/whitebox + * @library /testlibrary /../../test/lib * @build MallocTrackingVerify * @run main ClassFileInstaller sun.hotspot.WhiteBox * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:NativeMemoryTracking=detail MallocTrackingVerify diff --git a/hotspot/test/runtime/NMT/ReleaseCommittedMemory.java b/hotspot/test/runtime/NMT/ReleaseCommittedMemory.java index 64ef463e5c0..91790adcd64 100644 --- a/hotspot/test/runtime/NMT/ReleaseCommittedMemory.java +++ b/hotspot/test/runtime/NMT/ReleaseCommittedMemory.java @@ -26,7 +26,7 @@ * @bug 8013120 * @summary Release committed memory and make sure NMT handles it correctly * @key nmt regression - * @library /testlibrary /testlibrary/whitebox + * @library /testlibrary /../../test/lib * @build ReleaseCommittedMemory * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/runtime/NMT/ReleaseNoCommit.java b/hotspot/test/runtime/NMT/ReleaseNoCommit.java index 94fba371df6..227c1dbb351 100644 --- a/hotspot/test/runtime/NMT/ReleaseNoCommit.java +++ b/hotspot/test/runtime/NMT/ReleaseNoCommit.java @@ -25,7 +25,7 @@ * @test * @summary Release uncommitted memory and make sure NMT handles it correctly * @key nmt regression - * @library /testlibrary /testlibrary/whitebox + * @library /testlibrary /../../test/lib * @build ReleaseNoCommit * @run main ClassFileInstaller sun.hotspot.WhiteBox * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:NativeMemoryTracking=summary ReleaseNoCommit diff --git a/hotspot/test/runtime/NMT/SummarySanityCheck.java b/hotspot/test/runtime/NMT/SummarySanityCheck.java index 04185bb492d..183e791215f 100644 --- a/hotspot/test/runtime/NMT/SummarySanityCheck.java +++ b/hotspot/test/runtime/NMT/SummarySanityCheck.java @@ -25,7 +25,7 @@ * @test * @key nmt jcmd * @summary Sanity check the output of NMT - * @library /testlibrary /testlibrary/whitebox + * @library /testlibrary /../../test/lib * @build SummarySanityCheck * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/runtime/NMT/ThreadedMallocTestType.java b/hotspot/test/runtime/NMT/ThreadedMallocTestType.java index 036db1ea3c0..c67ea6e7f13 100644 --- a/hotspot/test/runtime/NMT/ThreadedMallocTestType.java +++ b/hotspot/test/runtime/NMT/ThreadedMallocTestType.java @@ -24,7 +24,7 @@ /* * @test * @key nmt jcmd - * @library /testlibrary /testlibrary/whitebox + * @library /testlibrary /../../test/lib * @build ThreadedMallocTestType * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/runtime/NMT/ThreadedVirtualAllocTestType.java b/hotspot/test/runtime/NMT/ThreadedVirtualAllocTestType.java index c0bb7616cbd..2d18b799c08 100644 --- a/hotspot/test/runtime/NMT/ThreadedVirtualAllocTestType.java +++ b/hotspot/test/runtime/NMT/ThreadedVirtualAllocTestType.java @@ -24,7 +24,7 @@ /* * @test * @key nmt jcmd - * @library /testlibrary /testlibrary/whitebox + * @library /testlibrary /../../test/lib * @build ThreadedVirtualAllocTestType * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/runtime/NMT/VirtualAllocCommitUncommitRecommit.java b/hotspot/test/runtime/NMT/VirtualAllocCommitUncommitRecommit.java index 2524e233ca3..d0fc8799363 100644 --- a/hotspot/test/runtime/NMT/VirtualAllocCommitUncommitRecommit.java +++ b/hotspot/test/runtime/NMT/VirtualAllocCommitUncommitRecommit.java @@ -25,7 +25,7 @@ * @test * @summary Test reserve/commit/uncommit/release of virtual memory and that we track it correctly * @key nmt jcmd - * @library /testlibrary /testlibrary/whitebox + * @library /testlibrary /../../test/lib * @build VirtualAllocCommitUncommitRecommit * @run main ClassFileInstaller sun.hotspot.WhiteBox * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:NativeMemoryTracking=detail VirtualAllocCommitUncommitRecommit diff --git a/hotspot/test/runtime/NMT/VirtualAllocTestType.java b/hotspot/test/runtime/NMT/VirtualAllocTestType.java index 579fba6b44f..665f5eba3af 100644 --- a/hotspot/test/runtime/NMT/VirtualAllocTestType.java +++ b/hotspot/test/runtime/NMT/VirtualAllocTestType.java @@ -25,7 +25,7 @@ * @test * @summary Test Reserve/Commit/Uncommit/Release of virtual memory and that we track it correctly * @key nmt jcmd - * @library /testlibrary /testlibrary/whitebox + * @library /testlibrary /../../test/lib * @build VirtualAllocTestType * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/runtime/Safepoint/AssertSafepointCheckConsistency1.java b/hotspot/test/runtime/Safepoint/AssertSafepointCheckConsistency1.java new file mode 100644 index 00000000000..01efb5f1119 --- /dev/null +++ b/hotspot/test/runtime/Safepoint/AssertSafepointCheckConsistency1.java @@ -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 + * @bug 8047290 + * @summary Ensure that a Monitor::lock_without_safepoint_check fires an assert when it incorrectly acquires a lock which must always have safepoint checks. + * @library /testlibrary /../../test/lib + * @build AssertSafepointCheckConsistency1 + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission + * @run main AssertSafepointCheckConsistency1 + */ + +import com.oracle.java.testlibrary.*; + +import sun.hotspot.WhiteBox; + +public class AssertSafepointCheckConsistency1 { + public static void main(String args[]) throws Exception { + if (args.length > 0) { + WhiteBox.getWhiteBox().assertMatchingSafepointCalls(true, true); + } + if (Platform.isDebugBuild()){ + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( + "-Xbootclasspath/a:.", + "-XX:+UnlockDiagnosticVMOptions", + "-XX:+WhiteBoxAPI", + "-XX:-TransmitErrorReport", + "-Xmx32m", + "AssertSafepointCheckConsistency1", + "test"); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldContain("assert").shouldContain("always"); + } + } +} + + diff --git a/hotspot/test/runtime/Safepoint/AssertSafepointCheckConsistency2.java b/hotspot/test/runtime/Safepoint/AssertSafepointCheckConsistency2.java new file mode 100644 index 00000000000..16f776f737f --- /dev/null +++ b/hotspot/test/runtime/Safepoint/AssertSafepointCheckConsistency2.java @@ -0,0 +1,58 @@ +/* + * 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 8047290 + * @summary Ensure that a Monitor::lock fires an assert when it incorrectly acquires a lock which must never have safepoint checks. + * @library /testlibrary /../../test/lib + * @build AssertSafepointCheckConsistency2 + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission + * @run main AssertSafepointCheckConsistency2 + */ + +import com.oracle.java.testlibrary.*; + +import sun.hotspot.WhiteBox; + +public class AssertSafepointCheckConsistency2 { + public static void main(String args[]) throws Exception { + if (args.length > 0) { + WhiteBox.getWhiteBox().assertMatchingSafepointCalls(false, false); + } + if (Platform.isDebugBuild()){ + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( + "-Xbootclasspath/a:.", + "-XX:+UnlockDiagnosticVMOptions", + "-XX:+WhiteBoxAPI", + "-XX:-TransmitErrorReport", + "-Xmx32m", + "AssertSafepointCheckConsistency2", + "test"); + + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldContain("assert").shouldContain("never"); + } + } +} diff --git a/hotspot/test/runtime/Safepoint/AssertSafepointCheckConsistency3.java b/hotspot/test/runtime/Safepoint/AssertSafepointCheckConsistency3.java new file mode 100644 index 00000000000..aa89c09edc3 --- /dev/null +++ b/hotspot/test/runtime/Safepoint/AssertSafepointCheckConsistency3.java @@ -0,0 +1,60 @@ +/* + * 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 8047290 + * @summary Ensure that Monitor::lock_without_safepoint_check does not assert when it correctly acquires a lock which must never have safepoint checks. + * @library /testlibrary /../../test/lib + * @build AssertSafepointCheckConsistency3 + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission + * @run main AssertSafepointCheckConsistency3 + */ + +import com.oracle.java.testlibrary.*; + +import sun.hotspot.WhiteBox; + +public class AssertSafepointCheckConsistency3 { + public static void main(String args[]) throws Exception { + if (args.length > 0) { + WhiteBox.getWhiteBox().assertMatchingSafepointCalls(false, true); + } + if (Platform.isDebugBuild()){ + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( + "-Xbootclasspath/a:.", + "-XX:+UnlockDiagnosticVMOptions", + "-XX:+WhiteBoxAPI", + "-XX:-TransmitErrorReport", + "-Xmx32m", + "AssertSafepointCheckConsistency3", + "test"); + + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldNotContain("assert"); + output.shouldNotContain("never"); + output.shouldNotContain("always"); + } + } +} diff --git a/hotspot/test/runtime/Safepoint/AssertSafepointCheckConsistency4.java b/hotspot/test/runtime/Safepoint/AssertSafepointCheckConsistency4.java new file mode 100644 index 00000000000..f6b89143001 --- /dev/null +++ b/hotspot/test/runtime/Safepoint/AssertSafepointCheckConsistency4.java @@ -0,0 +1,62 @@ +/* + * 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 8047290 + * @summary Ensure that Monitor::lock does not assert when it correctly acquires a lock which must always have safepoint checks. + * @library /testlibrary /../../test/lib + * @build AssertSafepointCheckConsistency4 + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission + * @run main AssertSafepointCheckConsistency4 + */ + +import com.oracle.java.testlibrary.*; + +import sun.hotspot.WhiteBox; + +public class AssertSafepointCheckConsistency4 { + public static void main(String args[]) throws Exception { + if (args.length > 0) { + WhiteBox.getWhiteBox().assertMatchingSafepointCalls(true, false); + } + if (Platform.isDebugBuild()){ + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( + "-Xbootclasspath/a:.", + "-XX:+UnlockDiagnosticVMOptions", + "-XX:+WhiteBoxAPI", + "-XX:-TransmitErrorReport", + "-Xmx32m", + "AssertSafepointCheckConsistency4", + "test"); + + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldNotContain("assert"); + output.shouldNotContain("never"); + output.shouldNotContain("always"); + } + } +} + + diff --git a/hotspot/test/runtime/SharedArchiveFile/LimitSharedSizes.java b/hotspot/test/runtime/SharedArchiveFile/LimitSharedSizes.java index b2505be0d7d..f38b85ad9af 100644 --- a/hotspot/test/runtime/SharedArchiveFile/LimitSharedSizes.java +++ b/hotspot/test/runtime/SharedArchiveFile/LimitSharedSizes.java @@ -30,40 +30,96 @@ import com.oracle.java.testlibrary.*; public class LimitSharedSizes { + static enum Region { + RO, RW, MD, MC + } + private static class SharedSizeTestData { public String optionName; public String optionValue; public String expectedErrorMsg; - public SharedSizeTestData(String name, String value, String msg) { - optionName = name; + public SharedSizeTestData(Region region, String value, String msg) { + optionName = getName(region); optionValue = value; expectedErrorMsg = msg; } + + public SharedSizeTestData(Region region, String msg) { + optionName = getName(region); + optionValue = getValue(region); + expectedErrorMsg = msg; + } + + private String getName(Region region) { + String name; + switch (region) { + case RO: + name = "-XX:SharedReadOnlySize"; + break; + case RW: + name = "-XX:SharedReadWriteSize"; + break; + case MD: + name = "-XX:SharedMiscDataSize"; + break; + case MC: + name = "-XX:SharedMiscCodeSize"; + break; + default: + name = "Unknown"; + break; + } + return name; + } + + private String getValue(Region region) { + String value; + switch (region) { + case RO: + value = Platform.is64bit() ? "9M" : "8M"; + break; + case RW: + value = Platform.is64bit() ? "12M" : "7M"; + break; + case MD: + value = Platform.is64bit() ? "4M" : "2M"; + break; + case MC: + value = "120k"; + break; + default: + value = "0M"; + break; + } + return value; + } } private static final SharedSizeTestData[] testTable = { - // values in this part of the test table should cause failure - // (shared space sizes are deliberately too small) - new SharedSizeTestData("-XX:SharedReadOnlySize", "4M", "read only"), - new SharedSizeTestData("-XX:SharedReadWriteSize","4M", "read write"), - - // Known issue, JDK-8038422 (assert() on Windows) - // new SharedSizeTestData("-XX:SharedMiscDataSize", "500k", "miscellaneous data"), - - // Too small of a misc code size should not cause a vm crash. - // It should result in the following error message: + // Too small of a region size should not cause a vm crash. + // It should result in an error message like the following: // The shared miscellaneous code space is not large enough // to preload requested classes. Use -XX:SharedMiscCodeSize= // to increase the initial size of shared miscellaneous code space. - new SharedSizeTestData("-XX:SharedMiscCodeSize", "20k", "miscellaneous code"), + new SharedSizeTestData(Region.RO, "4M", "read only"), + new SharedSizeTestData(Region.RW, "4M", "read write"), + new SharedSizeTestData(Region.MD, "50k", "miscellaneous data"), + new SharedSizeTestData(Region.MC, "20k", "miscellaneous code"), // these values are larger than default ones, but should // be acceptable and not cause failure - new SharedSizeTestData("-XX:SharedReadOnlySize", "20M", null), - new SharedSizeTestData("-XX:SharedReadWriteSize", "20M", null), - new SharedSizeTestData("-XX:SharedMiscDataSize", "20M", null), - new SharedSizeTestData("-XX:SharedMiscCodeSize", "20M", null) + new SharedSizeTestData(Region.RO, "20M", null), + new SharedSizeTestData(Region.RW, "20M", null), + new SharedSizeTestData(Region.MD, "20M", null), + new SharedSizeTestData(Region.MC, "20M", null), + + // test with sizes which just meet the minimum required sizes + // the following tests also attempt to use the shared archive + new SharedSizeTestData(Region.RO, "UseArchive"), + new SharedSizeTestData(Region.RW, "UseArchive"), + new SharedSizeTestData(Region.MD, "UseArchive"), + new SharedSizeTestData(Region.MC, "UseArchive") }; public static void main(String[] args) throws Exception { @@ -82,10 +138,39 @@ public class LimitSharedSizes { OutputAnalyzer output = new OutputAnalyzer(pb.start()); if (td.expectedErrorMsg != null) { - output.shouldContain("The shared " + td.expectedErrorMsg - + " space is not large enough"); + if (!td.expectedErrorMsg.equals("UseArchive")) { + output.shouldContain("The shared " + td.expectedErrorMsg + + " space is not large enough"); - output.shouldHaveExitValue(2); + output.shouldHaveExitValue(2); + } else { + output.shouldNotContain("space is not large enough"); + output.shouldHaveExitValue(0); + + // try to use the archive + pb = ProcessTools.createJavaProcessBuilder( + "-XX:+UnlockDiagnosticVMOptions", + "-XX:SharedArchiveFile=./" + fileName, + "-XX:+PrintSharedArchiveAndExit", + "-version"); + + try { + output = new OutputAnalyzer(pb.start()); + output.shouldContain("archive is valid"); + } catch (RuntimeException e) { + // if sharing failed due to ASLR or similar reasons, + // check whether sharing was attempted at all (UseSharedSpaces) + if ((output.getOutput().contains("Unable to use shared archive") || + output.getOutput().contains("Unable to map ReadOnly shared space at required address.") || + output.getOutput().contains("Unable to map ReadWrite shared space at required address.") || + output.getOutput().contains("Unable to reserve shared space at required address")) && + output.getExitValue() == 1) { + System.out.println("Unable to use shared archive: test not executed; assumed passed"); + return; + } + } + output.shouldHaveExitValue(0); + } } else { output.shouldNotContain("space is not large enough"); output.shouldHaveExitValue(0); diff --git a/hotspot/test/runtime/SharedArchiveFile/PrintSharedArchiveAndExit.java b/hotspot/test/runtime/SharedArchiveFile/PrintSharedArchiveAndExit.java new file mode 100644 index 00000000000..e3e81ca9d43 --- /dev/null +++ b/hotspot/test/runtime/SharedArchiveFile/PrintSharedArchiveAndExit.java @@ -0,0 +1,83 @@ +/* + * 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 8066670 + * @summary Testing -XX:+PrintSharedArchiveAndExit option + * @library /testlibrary + */ + +import com.oracle.java.testlibrary.*; + +public class PrintSharedArchiveAndExit { + public static void main(String[] args) throws Exception { + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( + "-XX:+UnlockDiagnosticVMOptions", "-XX:SharedArchiveFile=./sample.jsa", "-Xshare:dump"); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + try { + output.shouldContain("Loading classes to share"); + output.shouldHaveExitValue(0); + + // (1) With a valid archive + pb = ProcessTools.createJavaProcessBuilder( + "-XX:+UnlockDiagnosticVMOptions", "-XX:SharedArchiveFile=./sample.jsa", + "-XX:+PrintSharedArchiveAndExit", "-version"); + output = new OutputAnalyzer(pb.start()); + output.shouldContain("archive is valid"); + output.shouldNotContain("java version"); // Should not print JVM version + output.shouldHaveExitValue(0); // Should report success in error code. + + pb = ProcessTools.createJavaProcessBuilder( + "-XX:+UnlockDiagnosticVMOptions", "-XX:SharedArchiveFile=./sample.jsa", + "-XX:+PrintSharedArchiveAndExit"); + output = new OutputAnalyzer(pb.start()); + output.shouldContain("archive is valid"); + output.shouldNotContain("Usage:"); // Should not print JVM help message + output.shouldHaveExitValue(0); // Should report success in error code. + + // (2) With an invalid archive (boot class path has been prepended) + pb = ProcessTools.createJavaProcessBuilder( + "-Xbootclasspath/p:foo.jar", + "-XX:+UnlockDiagnosticVMOptions", "-XX:SharedArchiveFile=./sample.jsa", + "-XX:+PrintSharedArchiveAndExit", "-version"); + output = new OutputAnalyzer(pb.start()); + output.shouldContain("archive is invalid"); + output.shouldNotContain("java version"); // Should not print JVM version + output.shouldHaveExitValue(1); // Should report failure in error code. + + pb = ProcessTools.createJavaProcessBuilder( + "-Xbootclasspath/p:foo.jar", + "-XX:+UnlockDiagnosticVMOptions", "-XX:SharedArchiveFile=./sample.jsa", + "-XX:+PrintSharedArchiveAndExit"); + output = new OutputAnalyzer(pb.start()); + output.shouldContain("archive is invalid"); + output.shouldNotContain("Usage:"); // Should not print JVM help message + output.shouldHaveExitValue(1); // Should report failure in error code. + } catch (RuntimeException e) { + e.printStackTrace(); + output.shouldContain("Unable to use shared archive"); + output.shouldHaveExitValue(1); + } + } +} diff --git a/hotspot/test/runtime/interned/SanityTest.java b/hotspot/test/runtime/interned/SanityTest.java index 84bc1fee7e5..76ddb284521 100644 --- a/hotspot/test/runtime/interned/SanityTest.java +++ b/hotspot/test/runtime/interned/SanityTest.java @@ -24,7 +24,7 @@ /* * @test SanityTest * @summary Sanity check of String.intern() & GC - * @library /testlibrary /testlibrary/whitebox + * @library /testlibrary /../../test/lib * @build SanityTest * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/runtime/memory/ReadFromNoaccessArea.java b/hotspot/test/runtime/memory/ReadFromNoaccessArea.java index 7a6c71d4b4d..77ad2de1688 100644 --- a/hotspot/test/runtime/memory/ReadFromNoaccessArea.java +++ b/hotspot/test/runtime/memory/ReadFromNoaccessArea.java @@ -24,7 +24,7 @@ /* * @test * @summary Test that touching noaccess area in class ReservedHeapSpace results in SIGSEGV/ACCESS_VIOLATION - * @library /testlibrary /testlibrary/whitebox + * @library /testlibrary /../../test/lib * @build ReadFromNoaccessArea * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/runtime/memory/ReadVMPageSize.java b/hotspot/test/runtime/memory/ReadVMPageSize.java index a32822040d6..feb69ac8773 100644 --- a/hotspot/test/runtime/memory/ReadVMPageSize.java +++ b/hotspot/test/runtime/memory/ReadVMPageSize.java @@ -24,7 +24,7 @@ /* * @test * @summary Using WhiteBox to get VM page size - * @library /testlibrary /testlibrary/whitebox + * @library /testlibrary /../../test/lib * @build ReadVMPageSize * @run main ClassFileInstaller sun.hotspot.WhiteBox * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI ReadVMPageSize diff --git a/hotspot/test/runtime/memory/ReserveMemory.java b/hotspot/test/runtime/memory/ReserveMemory.java index 1708657f34c..76e6c5b12d7 100644 --- a/hotspot/test/runtime/memory/ReserveMemory.java +++ b/hotspot/test/runtime/memory/ReserveMemory.java @@ -26,7 +26,7 @@ * @key regression * @bug 8012015 * @summary Make sure reserved (but uncommitted) memory is not accessible - * @library /testlibrary /testlibrary/whitebox + * @library /testlibrary /../../test/lib * @build ReserveMemory * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/runtime/memory/RunUnitTestsConcurrently.java b/hotspot/test/runtime/memory/RunUnitTestsConcurrently.java index e979504c664..34576662150 100644 --- a/hotspot/test/runtime/memory/RunUnitTestsConcurrently.java +++ b/hotspot/test/runtime/memory/RunUnitTestsConcurrently.java @@ -24,7 +24,7 @@ /* * @test * @summary Test launches unit tests inside vm concurrently - * @library /testlibrary /testlibrary/whitebox + * @library /testlibrary /../../test/lib * @build RunUnitTestsConcurrently * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/runtime/memory/StressVirtualSpaceResize.java b/hotspot/test/runtime/memory/StressVirtualSpaceResize.java index ebe5110a64f..67ef73385ac 100644 --- a/hotspot/test/runtime/memory/StressVirtualSpaceResize.java +++ b/hotspot/test/runtime/memory/StressVirtualSpaceResize.java @@ -24,7 +24,7 @@ /* * @test * @summary Stress test that expands/shrinks VirtualSpace - * @library /testlibrary /testlibrary/whitebox + * @library /testlibrary /../../test/lib * @build StressVirtualSpaceResize * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/runtime/whitebox/WBStackSize.java b/hotspot/test/runtime/whitebox/WBStackSize.java index b487bb472bc..b3226974553 100644 --- a/hotspot/test/runtime/whitebox/WBStackSize.java +++ b/hotspot/test/runtime/whitebox/WBStackSize.java @@ -24,7 +24,7 @@ /* * @test WBStackSize * @summary verify that whitebox functions getThreadFullStackSize() and getThreadRemainingStackSize are working - * @library /testlibrary /testlibrary/whitebox + * @library /testlibrary /../../test/lib * @build WBStackSize * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/sanity/WBApi.java b/hotspot/test/sanity/WBApi.java index 58c100f496e..a1418e170fd 100644 --- a/hotspot/test/sanity/WBApi.java +++ b/hotspot/test/sanity/WBApi.java @@ -24,7 +24,7 @@ /* * @test WBApi * @summary verify that whitebox functions can be linked and executed - * @library /testlibrary /testlibrary/whitebox + * @library /testlibrary /../../test/lib * @build WBApi * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/serviceability/ParserTest.java b/hotspot/test/serviceability/ParserTest.java index 5a0f488f0d9..37a35de9a91 100644 --- a/hotspot/test/serviceability/ParserTest.java +++ b/hotspot/test/serviceability/ParserTest.java @@ -24,7 +24,7 @@ /* * @test * @summary Test that the diagnostic command arguemnt parser works - * @library /testlibrary /testlibrary/whitebox + * @library /testlibrary /../../test/lib * @build ClassFileInstaller sun.hotspot.WhiteBox sun.hotspot.parser.* * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/serviceability/sa/jmap-hashcode/Test8028623.java b/hotspot/test/serviceability/sa/jmap-hashcode/Test8028623.java index 10877ba86d9..169c0432999 100644 --- a/hotspot/test/serviceability/sa/jmap-hashcode/Test8028623.java +++ b/hotspot/test/serviceability/sa/jmap-hashcode/Test8028623.java @@ -41,12 +41,12 @@ import java.io.File; public class Test8028623 { - public static int à = 1; + public static int \u00CB = 1; public static String dumpFile = "heap.out"; public static void main (String[] args) { - System.out.println(Ã); + System.out.println(\u00CB); try { if (!Platform.shouldSAAttach()) { diff --git a/hotspot/test/testlibrary/com/oracle/java/testlibrary/Utils.java b/hotspot/test/testlibrary/com/oracle/java/testlibrary/Utils.java index 96d165fd086..ddd16f8ab2f 100644 --- a/hotspot/test/testlibrary/com/oracle/java/testlibrary/Utils.java +++ b/hotspot/test/testlibrary/com/oracle/java/testlibrary/Utils.java @@ -32,13 +32,18 @@ import java.lang.reflect.Field; import java.net.InetAddress; import java.net.ServerSocket; import java.net.UnknownHostException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Random; +import java.util.concurrent.TimeUnit; import java.util.regex.Matcher; import java.util.regex.Pattern; +import java.util.stream.Collectors; import sun.misc.Unsafe; /** @@ -88,6 +93,12 @@ public final class Utils { TIMEOUT_FACTOR = Double.parseDouble(toFactor); } + /** + * Returns the value of JTREG default test timeout in milliseconds + * converted to {@code long}. + */ + public static final long DEFAULT_TEST_TIMEOUT = TimeUnit.SECONDS.toMillis(120); + private Utils() { // Private constructor to prevent class instantiation } @@ -318,28 +329,15 @@ public final class Utils { * or null if not found. * @param filename name of the file to read * @return String contents of file, or null if file not found. + * @throws IOException + * if an I/O error occurs reading from the file or a malformed or + * unmappable byte sequence is read */ - public static String fileAsString(String filename) { - StringBuilder result = new StringBuilder(); - try { - File file = new File(filename); - if (file.exists()) { - BufferedReader reader = new BufferedReader(new FileReader(file)); - while (true) { - String line = reader.readLine(); - if (line == null) { - break; - } - result.append(line).append("\n"); - } - } else { - // Does not exist: - return null; - } - } catch (Exception e) { - e.printStackTrace(); - } - return result.toString(); + public static String fileAsString(String filename) throws IOException { + Path filePath = Paths.get(filename); + return Files.exists(filePath) + ? Files.lines(filePath).collect(Collectors.joining(NEW_LINE)) + : null; } /** @@ -396,4 +394,14 @@ public final class Utils { } return RANDOM_GENERATOR; } + + /** + * Adjusts the provided timeout value for the TIMEOUT_FACTOR + * @param tOut the timeout value to be adjusted + * @return The timeout value adjusted for the value of "test.timeout.factor" + * system property + */ + public static long adjustTimeout(long tOut) { + return Math.round(tOut * Utils.TIMEOUT_FACTOR); + } } diff --git a/hotspot/test/testlibrary/com/oracle/java/testlibrary/cli/CommandLineOptionTest.java b/hotspot/test/testlibrary/com/oracle/java/testlibrary/cli/CommandLineOptionTest.java index 8da6c0264ef..807a3aba664 100644 --- a/hotspot/test/testlibrary/com/oracle/java/testlibrary/cli/CommandLineOptionTest.java +++ b/hotspot/test/testlibrary/com/oracle/java/testlibrary/cli/CommandLineOptionTest.java @@ -49,7 +49,7 @@ public abstract class CommandLineOptionTest { private static final String PRINT_FLAGS_FINAL_FORMAT = "%s\\s*:?=\\s*%s"; /** - * Verifies that JVM startup behaviour matches our expectations. + * Verifies that JVM startup behavior matches our expectations. * * @param option an option that should be passed to JVM * @param expectedMessages an array of patterns that should occur @@ -58,18 +58,24 @@ public abstract class CommandLineOptionTest { * @param unexpectedMessages an array of patterns that should not * occur in JVM output. If {@code null} then * JVM output could be empty. + * @param exitErrorMessage message that will be shown if exit code is not + * as expected. + * @param wrongWarningMessage message that will be shown if warning + * messages are not as expected. * @param exitCode expected exit code. * @throws Throwable if verification fails or some other issues occur. */ public static void verifyJVMStartup(String option, String expectedMessages[], String unexpectedMessages[], + String exitErrorMessage, String wrongWarningMessage, ExitCode exitCode) throws Throwable { CommandLineOptionTest.verifyJVMStartup(expectedMessages, - unexpectedMessages, exitCode, false, option); + unexpectedMessages, exitErrorMessage, + wrongWarningMessage, exitCode, false, option); } /** - * Verifies that JVM startup behaviour matches our expectations. + * Verifies that JVM startup behavior matches our expectations. * * @param expectedMessages an array of patterns that should occur * in JVM output. If {@code null} then @@ -77,6 +83,10 @@ public abstract class CommandLineOptionTest { * @param unexpectedMessages an array of patterns that should not * occur in JVM output. If {@code null} then * JVM output could be empty. + * @param exitErrorMessage message that will be shown if exit code is not + * as expected. + * @param wrongWarningMessage message that will be shown if warning + * messages are not as expected. * @param exitCode expected exit code. * @param addTestVMOptions if {@code true} then test VM options will be * passed to VM. @@ -85,8 +95,10 @@ public abstract class CommandLineOptionTest { * @throws Throwable if verification fails or some other issues occur. */ public static void verifyJVMStartup(String expectedMessages[], - String unexpectedMessages[], ExitCode exitCode, - boolean addTestVMOptions, String... options) throws Throwable { + String unexpectedMessages[], String exitErrorMessage, + String wrongWarningMessage, ExitCode exitCode, + boolean addTestVMOptions, String... options) + throws Throwable { List finalOptions = new ArrayList<>(); if (addTestVMOptions) { Collections.addAll(finalOptions, Utils.getTestJavaOpts()); @@ -99,23 +111,46 @@ public abstract class CommandLineOptionTest { new String[finalOptions.size()])); OutputAnalyzer outputAnalyzer = new OutputAnalyzer(processBuilder.start()); - outputAnalyzer.shouldHaveExitValue(exitCode.value); + + try { + outputAnalyzer.shouldHaveExitValue(exitCode.value); + } catch (RuntimeException e) { + String errorMessage = String.format( + "JVM process should have exit value '%d'.%n%s", + exitCode.value, exitErrorMessage); + throw new AssertionError(errorMessage, e); + } + if (expectedMessages != null) { for (String expectedMessage : expectedMessages) { - outputAnalyzer.shouldMatch(expectedMessage); + try { + outputAnalyzer.shouldMatch(expectedMessage); + } catch (RuntimeException e) { + String errorMessage = String.format( + "Expected message not found: '%s'.%n%s", + expectedMessage, wrongWarningMessage); + throw new AssertionError(errorMessage, e); + } } } if (unexpectedMessages != null) { for (String unexpectedMessage : unexpectedMessages) { - outputAnalyzer.shouldNotMatch(unexpectedMessage); + try { + outputAnalyzer.shouldNotMatch(unexpectedMessage); + } catch (RuntimeException e) { + String errorMessage = String.format( + "Unexpected message found: '%s'.%n%s", + unexpectedMessage, wrongWarningMessage); + throw new AssertionError(errorMessage, e); + } } } } /** - * Verifies that JVM startup behaviour matches our expectations when type + * Verifies that JVM startup behavior matches our expectations when type * of newly started VM is the same as the type of current. * * @param expectedMessages an array of patterns that should occur @@ -124,20 +159,26 @@ public abstract class CommandLineOptionTest { * @param unexpectedMessages an array of patterns that should not * occur in JVM output. If {@code null} then * JVM output could be empty. + * @param exitErrorMessage Message that will be shown if exit value is not + * as expected. + * @param wrongWarningMessage message that will be shown if warning + * messages are not as expected. * @param exitCode expected exit code. * @param options options that should be passed to VM in addition to mode * flag. * @throws Throwable if verification fails or some other issues occur. */ public static void verifySameJVMStartup(String expectedMessages[], - String unexpectedMessages[], ExitCode exitCode, String... options) - throws Throwable { + String unexpectedMessages[], String exitErrorMessage, + String wrongWarningMessage, ExitCode exitCode, String... options) + throws Throwable { List finalOptions = new ArrayList<>(); finalOptions.add(CommandLineOptionTest.getVMTypeOption()); Collections.addAll(finalOptions, options); CommandLineOptionTest.verifyJVMStartup(expectedMessages, - unexpectedMessages, exitCode, false, + unexpectedMessages, exitErrorMessage, + wrongWarningMessage, exitCode, false, finalOptions.toArray(new String[finalOptions.size()])); } @@ -149,13 +190,17 @@ public abstract class CommandLineOptionTest { * * @param optionName a name of tested option. * @param expectedValue expected value of tested option. + * @param optionErrorString message will be shown if option value is not as + * expected. * @param additionalVMOpts additional options that should be * passed to JVM. * @throws Throwable if verification fails or some other issues occur. */ public static void verifyOptionValue(String optionName, - String expectedValue, String... additionalVMOpts) throws Throwable { - verifyOptionValue(optionName, expectedValue, true, additionalVMOpts); + String expectedValue, String optionErrorString, + String... additionalVMOpts) throws Throwable { + verifyOptionValue(optionName, expectedValue, optionErrorString, + true, additionalVMOpts); } /** @@ -168,14 +213,17 @@ public abstract class CommandLineOptionTest { * @param expectedValue expected value of tested option. * @param addTestVmOptions if {@code true}, then test VM options * will be used. + * @param optionErrorString message will be shown if option value is not as + * expected. * @param additionalVMOpts additional options that should be * passed to JVM. * @throws Throwable if verification fails or some other issues * occur. */ public static void verifyOptionValue(String optionName, - String expectedValue, boolean addTestVmOptions, - String... additionalVMOpts) throws Throwable { + String expectedValue, String optionErrorString, + boolean addTestVmOptions, String... additionalVMOpts) + throws Throwable { List vmOpts = new ArrayList<>(); if (addTestVmOptions) { @@ -191,10 +239,25 @@ public abstract class CommandLineOptionTest { OutputAnalyzer outputAnalyzer = new OutputAnalyzer(processBuilder.start()); - outputAnalyzer.shouldHaveExitValue(0); + try { + outputAnalyzer.shouldHaveExitValue(0); + } catch (RuntimeException e) { + String errorMessage = String.format( + "JVM should start with option '%s' without errors.", + optionName); + throw new AssertionError(errorMessage, e); + } + try { outputAnalyzer.shouldMatch(String.format( CommandLineOptionTest.PRINT_FLAGS_FINAL_FORMAT, optionName, expectedValue)); + } catch (RuntimeException e) { + String errorMessage = String.format( + "Option '%s' is expected to have '%s' value%n%s", + optionName, expectedValue, + optionErrorString); + throw new AssertionError(errorMessage, e); + } } /** @@ -207,18 +270,21 @@ public abstract class CommandLineOptionTest { * * @param optionName name of tested option. * @param expectedValue expected value of tested option. + * @param optionErrorString message to show if option has another value * @param additionalVMOpts additional options that should be * passed to JVM. * @throws Throwable if verification fails or some other issues occur. */ public static void verifyOptionValueForSameVM(String optionName, - String expectedValue, String... additionalVMOpts) throws Throwable { + String expectedValue, String optionErrorString, + String... additionalVMOpts) throws Throwable { List finalOptions = new ArrayList<>(); finalOptions.add(CommandLineOptionTest.getVMTypeOption()); Collections.addAll(finalOptions, additionalVMOpts); CommandLineOptionTest.verifyOptionValue(optionName, expectedValue, - false, finalOptions.toArray(new String[finalOptions.size()])); + optionErrorString, false, + finalOptions.toArray(new String[finalOptions.size()])); } /** diff --git a/hotspot/test/testlibrary/ctw/test/ClassesDirTest.java b/hotspot/test/testlibrary/ctw/test/ClassesDirTest.java index 5cbaaf9a66a..656f36438c6 100644 --- a/hotspot/test/testlibrary/ctw/test/ClassesDirTest.java +++ b/hotspot/test/testlibrary/ctw/test/ClassesDirTest.java @@ -24,7 +24,7 @@ /* * @test * @bug 8012447 - * @library /testlibrary /testlibrary/whitebox /testlibrary/ctw/src + * @library /testlibrary /../../test/lib /testlibrary/ctw/src * @build ClassFileInstaller sun.hotspot.tools.ctw.CompileTheWorld sun.hotspot.WhiteBox Foo Bar * @run main ClassFileInstaller sun.hotspot.WhiteBox Foo Bar * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/testlibrary/ctw/test/ClassesListTest.java b/hotspot/test/testlibrary/ctw/test/ClassesListTest.java index ea8abe27106..8c92fb038a6 100644 --- a/hotspot/test/testlibrary/ctw/test/ClassesListTest.java +++ b/hotspot/test/testlibrary/ctw/test/ClassesListTest.java @@ -24,7 +24,7 @@ /* * @test * @bug 8012447 - * @library /testlibrary /testlibrary/whitebox /testlibrary/ctw/src + * @library /testlibrary /../../test/lib /testlibrary/ctw/src * @build ClassFileInstaller sun.hotspot.tools.ctw.CompileTheWorld sun.hotspot.WhiteBox Foo Bar * @run main ClassFileInstaller sun.hotspot.WhiteBox Foo Bar * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/testlibrary/ctw/test/JarDirTest.java b/hotspot/test/testlibrary/ctw/test/JarDirTest.java index 193aea4f647..fef89f8dd8d 100644 --- a/hotspot/test/testlibrary/ctw/test/JarDirTest.java +++ b/hotspot/test/testlibrary/ctw/test/JarDirTest.java @@ -24,7 +24,7 @@ /* * @test * @bug 8012447 - * @library /testlibrary /testlibrary/whitebox /testlibrary/ctw/src + * @library /testlibrary /../../test/lib /testlibrary/ctw/src * @build ClassFileInstaller com.oracle.java.testlibrary.* sun.hotspot.tools.ctw.CompileTheWorld sun.hotspot.WhiteBox Foo Bar * @run main ClassFileInstaller sun.hotspot.WhiteBox Foo Bar * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/testlibrary/ctw/test/JarsTest.java b/hotspot/test/testlibrary/ctw/test/JarsTest.java index 87bafe85898..277cc1f808a 100644 --- a/hotspot/test/testlibrary/ctw/test/JarsTest.java +++ b/hotspot/test/testlibrary/ctw/test/JarsTest.java @@ -24,7 +24,7 @@ /* * @test * @bug 8012447 - * @library /testlibrary /testlibrary/whitebox /testlibrary/ctw/src + * @library /testlibrary /../../test/lib /testlibrary/ctw/src * @build ClassFileInstaller com.oracle.java.testlibrary.* sun.hotspot.tools.ctw.CompileTheWorld sun.hotspot.WhiteBox Foo Bar * @run main ClassFileInstaller sun.hotspot.WhiteBox Foo Bar * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/testlibrary_tests/TestMutuallyExclusivePlatformPredicates.java b/hotspot/test/testlibrary_tests/TestMutuallyExclusivePlatformPredicates.java index 4735d5dbfb2..be8d04ff022 100644 --- a/hotspot/test/testlibrary_tests/TestMutuallyExclusivePlatformPredicates.java +++ b/hotspot/test/testlibrary_tests/TestMutuallyExclusivePlatformPredicates.java @@ -47,7 +47,8 @@ public class TestMutuallyExclusivePlatformPredicates { BITNESS("is32bit", "is64bit"), OS("isLinux", "isSolaris", "isWindows", "isOSX"), VM_TYPE("isClient", "isServer", "isGraal", "isMinimal"), - IGNORED("isEmbedded", "isDebugBuild"); + IGNORED("isEmbedded", "isDebugBuild", "shouldSAAttach", + "canPtraceAttachLinux", "canAttachOSX"); public final List methodNames; diff --git a/hotspot/test/testlibrary_tests/ctw/ClassesDirTest.java b/hotspot/test/testlibrary_tests/ctw/ClassesDirTest.java index 5cbaaf9a66a..656f36438c6 100644 --- a/hotspot/test/testlibrary_tests/ctw/ClassesDirTest.java +++ b/hotspot/test/testlibrary_tests/ctw/ClassesDirTest.java @@ -24,7 +24,7 @@ /* * @test * @bug 8012447 - * @library /testlibrary /testlibrary/whitebox /testlibrary/ctw/src + * @library /testlibrary /../../test/lib /testlibrary/ctw/src * @build ClassFileInstaller sun.hotspot.tools.ctw.CompileTheWorld sun.hotspot.WhiteBox Foo Bar * @run main ClassFileInstaller sun.hotspot.WhiteBox Foo Bar * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/testlibrary_tests/ctw/ClassesListTest.java b/hotspot/test/testlibrary_tests/ctw/ClassesListTest.java index ea8abe27106..8c92fb038a6 100644 --- a/hotspot/test/testlibrary_tests/ctw/ClassesListTest.java +++ b/hotspot/test/testlibrary_tests/ctw/ClassesListTest.java @@ -24,7 +24,7 @@ /* * @test * @bug 8012447 - * @library /testlibrary /testlibrary/whitebox /testlibrary/ctw/src + * @library /testlibrary /../../test/lib /testlibrary/ctw/src * @build ClassFileInstaller sun.hotspot.tools.ctw.CompileTheWorld sun.hotspot.WhiteBox Foo Bar * @run main ClassFileInstaller sun.hotspot.WhiteBox Foo Bar * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/testlibrary_tests/ctw/JarDirTest.java b/hotspot/test/testlibrary_tests/ctw/JarDirTest.java index 193aea4f647..fef89f8dd8d 100644 --- a/hotspot/test/testlibrary_tests/ctw/JarDirTest.java +++ b/hotspot/test/testlibrary_tests/ctw/JarDirTest.java @@ -24,7 +24,7 @@ /* * @test * @bug 8012447 - * @library /testlibrary /testlibrary/whitebox /testlibrary/ctw/src + * @library /testlibrary /../../test/lib /testlibrary/ctw/src * @build ClassFileInstaller com.oracle.java.testlibrary.* sun.hotspot.tools.ctw.CompileTheWorld sun.hotspot.WhiteBox Foo Bar * @run main ClassFileInstaller sun.hotspot.WhiteBox Foo Bar * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/testlibrary_tests/ctw/JarsTest.java b/hotspot/test/testlibrary_tests/ctw/JarsTest.java index 87bafe85898..277cc1f808a 100644 --- a/hotspot/test/testlibrary_tests/ctw/JarsTest.java +++ b/hotspot/test/testlibrary_tests/ctw/JarsTest.java @@ -24,7 +24,7 @@ /* * @test * @bug 8012447 - * @library /testlibrary /testlibrary/whitebox /testlibrary/ctw/src + * @library /testlibrary /../../test/lib /testlibrary/ctw/src * @build ClassFileInstaller com.oracle.java.testlibrary.* sun.hotspot.tools.ctw.CompileTheWorld sun.hotspot.WhiteBox Foo Bar * @run main ClassFileInstaller sun.hotspot.WhiteBox Foo Bar * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/testlibrary_tests/whitebox/vm_flags/BooleanTest.java b/hotspot/test/testlibrary_tests/whitebox/vm_flags/BooleanTest.java index 1da1728877d..1857c5828d2 100644 --- a/hotspot/test/testlibrary_tests/whitebox/vm_flags/BooleanTest.java +++ b/hotspot/test/testlibrary_tests/whitebox/vm_flags/BooleanTest.java @@ -24,7 +24,7 @@ /* * @test BooleanTest * @bug 8028756 - * @library /testlibrary /testlibrary/whitebox + * @library /testlibrary /../../test/lib * @build BooleanTest ClassFileInstaller sun.hotspot.WhiteBox com.oracle.java.testlibrary.* * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/testlibrary_tests/whitebox/vm_flags/DoubleTest.java b/hotspot/test/testlibrary_tests/whitebox/vm_flags/DoubleTest.java index 08fb73d87cf..d9cff2f6475 100644 --- a/hotspot/test/testlibrary_tests/whitebox/vm_flags/DoubleTest.java +++ b/hotspot/test/testlibrary_tests/whitebox/vm_flags/DoubleTest.java @@ -24,7 +24,7 @@ /* * @test DoubleTest * @bug 8028756 - * @library /testlibrary /testlibrary/whitebox + * @library /testlibrary /../../test/lib * @build DoubleTest * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/testlibrary_tests/whitebox/vm_flags/IntxTest.java b/hotspot/test/testlibrary_tests/whitebox/vm_flags/IntxTest.java index 9acdd31dd8b..dc37d7a2ed0 100644 --- a/hotspot/test/testlibrary_tests/whitebox/vm_flags/IntxTest.java +++ b/hotspot/test/testlibrary_tests/whitebox/vm_flags/IntxTest.java @@ -24,7 +24,7 @@ /* * @test IntxTest * @bug 8028756 - * @library /testlibrary /testlibrary/whitebox + * @library /testlibrary /../../test/lib * @build IntxTest * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/testlibrary_tests/whitebox/vm_flags/SizeTTest.java b/hotspot/test/testlibrary_tests/whitebox/vm_flags/SizeTTest.java index 51559cfbb53..9696bd36158 100644 --- a/hotspot/test/testlibrary_tests/whitebox/vm_flags/SizeTTest.java +++ b/hotspot/test/testlibrary_tests/whitebox/vm_flags/SizeTTest.java @@ -24,7 +24,7 @@ /* * @test SizeTTest * @bug 8054823 - * @library /testlibrary /testlibrary/whitebox + * @library /testlibrary /../../test/lib * @build SizeTTest * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/testlibrary_tests/whitebox/vm_flags/StringTest.java b/hotspot/test/testlibrary_tests/whitebox/vm_flags/StringTest.java index e613df85b78..ae26e370bcf 100644 --- a/hotspot/test/testlibrary_tests/whitebox/vm_flags/StringTest.java +++ b/hotspot/test/testlibrary_tests/whitebox/vm_flags/StringTest.java @@ -24,7 +24,7 @@ /* * @test StringTest * @bug 8028756 - * @library /testlibrary /testlibrary/whitebox + * @library /testlibrary /../../test/lib * @build StringTest * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/testlibrary_tests/whitebox/vm_flags/Uint64Test.java b/hotspot/test/testlibrary_tests/whitebox/vm_flags/Uint64Test.java index fd3a82c41e8..7ab5f318356 100644 --- a/hotspot/test/testlibrary_tests/whitebox/vm_flags/Uint64Test.java +++ b/hotspot/test/testlibrary_tests/whitebox/vm_flags/Uint64Test.java @@ -24,7 +24,7 @@ /* * @test Uint64Test * @bug 8028756 - * @library /testlibrary /testlibrary/whitebox + * @library /testlibrary /../../test/lib * @build Uint64Test * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/hotspot/test/testlibrary_tests/whitebox/vm_flags/UintxTest.java b/hotspot/test/testlibrary_tests/whitebox/vm_flags/UintxTest.java index bdb1f647209..469ecc2e59a 100644 --- a/hotspot/test/testlibrary_tests/whitebox/vm_flags/UintxTest.java +++ b/hotspot/test/testlibrary_tests/whitebox/vm_flags/UintxTest.java @@ -24,7 +24,7 @@ /* * @test UintxTest * @bug 8028756 - * @library /testlibrary /testlibrary/whitebox + * @library /testlibrary /../../test/lib * @build UintxTest * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission diff --git a/jaxp/.hgtags b/jaxp/.hgtags index 87019760616..bd9d0889f34 100644 --- a/jaxp/.hgtags +++ b/jaxp/.hgtags @@ -285,3 +285,5 @@ a12d347f84176200593999f4da91ae2bb86865b2 jdk9-b39 3f46e2196498de33e7c65efa7b372e46f1faba01 jdk9-b40 71dd8f7649428efd3a56ca5fefc80e59d37b8434 jdk9-b41 47b0d3fa4118b9d56870cf4004987438c501f5c0 jdk9-b42 +40b242363040229a05224fbc5dc203a3f46a8f8f jdk9-b43 +0cb0844b58924d6086d2850c22087d06679d5eef jdk9-b44 diff --git a/jaxp/test/Makefile b/jaxp/test/Makefile new file mode 100644 index 00000000000..0a3acdafb7c --- /dev/null +++ b/jaxp/test/Makefile @@ -0,0 +1,325 @@ +# +# 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 +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# 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. +# + +# +# Makefile to run various JAXP tests +# + +.DEFAULT : all + +# Empty these to get rid of some default rules +.SUFFIXES: +.SUFFIXES: .java +CO= +GET= + +# 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_) + +# Commands to run on paths to make mixed paths for java on windows +ifeq ($(UNAME_S), CYGWIN) + # Location of developer shared files + SLASH_JAVA = J: + GETMIXEDPATH = cygpath -m +else + # Location of developer shared files + SLASH_JAVA = /java + + GETMIXEDPATH=$(ECHO) +endif + +# Root of this test area (important to use full paths in some places) +TEST_ROOT := $(shell $(PWD)) + +# Root of all test results +ifdef ALT_OUTPUTDIR + ABS_OUTPUTDIR = $(shell $(CD) $(ALT_OUTPUTDIR) && $(PWD)) +else + ABS_OUTPUTDIR = $(shell $(CD) $(TEST_ROOT)/.. && $(PWD)) +endif + +ABS_PLATFORM_BUILD_ROOT = $(ABS_OUTPUTDIR) +ABS_TEST_OUTPUT_DIR := $(ABS_PLATFORM_BUILD_ROOT)/testoutput/$(UNIQUE_DIR) + +# Expect JPRT to set PRODUCT_HOME (the product or jdk in this case to test) +ifndef PRODUCT_HOME + # Try to use j2sdk-image if it exists + ABS_JDK_IMAGE = $(ABS_PLATFORM_BUILD_ROOT)/images/j2sdk-image + PRODUCT_HOME := \ + $(shell \ + if [ -d $(ABS_JDK_IMAGE) ] ; then \ + $(ECHO) "$(ABS_JDK_IMAGE)"; \ + else \ + $(ECHO) "$(ABS_PLATFORM_BUILD_ROOT)"; \ + fi) + PRODUCT_HOME := $(PRODUCT_HOME) +endif + +# Expect JPRT to set JPRT_PRODUCT_ARGS (e.g. -server etc.) +# Should be passed into 'java' only. +# Could include: -d64 -server -client OR any java option +ifdef JPRT_PRODUCT_ARGS + JAVA_ARGS = $(JPRT_PRODUCT_ARGS) +endif + +# Expect JPRT to set JPRT_PRODUCT_VM_ARGS (e.g. -Xcomp etc.) +# Should be passed into anything running the vm (java, javac, javadoc, ...). +ifdef JPRT_PRODUCT_VM_ARGS + JAVA_VM_ARGS = $(JPRT_PRODUCT_VM_ARGS) +endif + +# Expect JPRT to set JPRT_ARCHIVE_BUNDLE (path to zip bundle for results) +ifdef JPRT_ARCHIVE_BUNDLE + ARCHIVE_BUNDLE = $(JPRT_ARCHIVE_BUNDLE) +else + ARCHIVE_BUNDLE = $(ABS_TEST_OUTPUT_DIR)/ARCHIVE_BUNDLE.zip +endif + +# How to create the test bundle (pass or fail, we want to create this) +# 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 default JAXP tests) +all: jaxp_all + @$(ECHO) "Testing completed successfully" + +# Prep for output +# Change execute permissions on shared library files. +# Files in repositories should never have execute permissions, but +# there are some tests that have pre-built shared libraries, and these +# windows dll files must have execute permission. Adding execute +# permission may happen automatically on windows when using certain +# versions of mercurial but it cannot be guaranteed. And blindly +# adding execute permission might be seen as a mercurial 'change', so +# we avoid adding execute permission to repository files. But testing +# from a plain source tree needs the chmod a+rx. Applying the chmod to +# all shared libraries not just dll files. And with CYGWIN and sshd +# service, you may need CYGWIN=ntsec for this to work. +prep: + @$(MKDIR) -p $(ABS_TEST_OUTPUT_DIR) + @$(MKDIR) -p `$(DIRNAME) $(ARCHIVE_BUNDLE)` + @if [ ! -d $(TEST_ROOT)/../.hg ] ; then \ + $(FIND) $(TEST_ROOT) \( -name \*.dll -o -name \*.DLL -o -name \*.so \) \ + -exec $(CHMOD) a+rx {} \; ; \ + fi + +# Cleanup +clean: + @$(RM) -r $(ABS_TEST_OUTPUT_DIR) + @$(RM) $(ARCHIVE_BUNDLE) + +################################################################ + +# jtreg tests + +# Expect JT_HOME to be set for jtreg tests. (home for jtreg) +ifndef JT_HOME + JT_HOME = $(SLASH_JAVA)/re/jtreg/4.1/promoted/latest/binaries/jtreg + ifdef JPRT_JTREG_HOME + JT_HOME = $(JPRT_JTREG_HOME) + endif +endif + +# Problematic tests to be excluded +PROBLEM_LISTS=$(call MixedDirs,$(wildcard ProblemList.txt closed/ProblemList.txt)) + +# Create exclude list for this platform and arch +ifdef NO_EXCLUDES + JTREG_EXCLUSIONS = +else + JTREG_EXCLUSIONS = $(PROBLEM_LISTS:%=-exclude:%) +endif + +# convert list of directories to dos paths +define MixedDirs +$(foreach i,$1,$(shell $(GETMIXEDPATH) "${i}")) +endef + +define SummaryInfo +$(ECHO) "########################################################" +$(CAT) $(?:%=$(ABS_TEST_OUTPUT_DIR)/%/$(STATS_TXT_NAME)) +$(ECHO) "########################################################" +endef + +# ------------------------------------------------------------------ + +jaxp_%: + $(ECHO) "Running tests: $@" + for each in $@; do \ + $(MAKE) -j 1 TEST_SELECTION=":$$each" UNIQUE_DIR=$$each jtreg_tests; \ + done + +# ------------------------------------------------------------------ + +ifdef CONCURRENCY + EXTRA_JTREG_OPTIONS += -concurrency:$(CONCURRENCY) +endif + +# Default JTREG to run (win32 script works for everybody) +JTREG = $(JT_HOME)/win32/bin/jtreg +# run in agentvm mode +JTREG_BASIC_OPTIONS += -agentvm +# Only run automatic tests +JTREG_BASIC_OPTIONS += -a +# Always turn on assertions +JTREG_ASSERT_OPTION = -ea -esa +JTREG_BASIC_OPTIONS += $(JTREG_ASSERT_OPTION) +# 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) +# Multiple by 4 the timeout numbers +JTREG_TIMEOUT_OPTION = -timeoutFactor:4 +JTREG_BASIC_OPTIONS += $(JTREG_TIMEOUT_OPTION) +# Set the max memory for jtreg control vm +JTREG_MEMORY_OPTION = -J-Xmx512m +JTREG_BASIC_OPTIONS += $(JTREG_MEMORY_OPTION) +# Add any extra options +JTREG_BASIC_OPTIONS += $(EXTRA_JTREG_OPTIONS) +# Set other vm and test options +JTREG_TEST_OPTIONS = $(JAVA_ARGS:%=-javaoptions:%) $(JAVA_VM_ARGS:%=-vmoption:%) +# Set the GC options for test vms +#JTREG_GC_OPTION = -vmoption:-XX:+UseSerialGC +#JTREG_TEST_OPTIONS += $(JTREG_GC_OPTION) +# Set the max memory for jtreg target test vms +JTREG_TESTVM_MEMORY_OPTION = -vmoption:-Xmx512m +JTREG_TEST_OPTIONS += $(JTREG_TESTVM_MEMORY_OPTION) + +# Make sure jtreg exists +$(JTREG): $(JT_HOME) + +# Run jtreg +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 + +################################################################ + +# Phony targets (e.g. these are not filenames) +.PHONY: all clean prep $(PHONY_LIST) + +################################################################ diff --git a/jaxp/test/TEST.ROOT b/jaxp/test/TEST.ROOT index cc03bd9063d..a098ba22044 100644 --- a/jaxp/test/TEST.ROOT +++ b/jaxp/test/TEST.ROOT @@ -2,5 +2,7 @@ # It also contains test-suite configuration information. # Tests that must run in othervm mode -othervm.dirs=javax/xml/jaxp/unittest +othervm.dirs=javax/xml/jaxp +# Group definitions +groups=TEST.groups diff --git a/jaxp/test/TEST.groups b/jaxp/test/TEST.groups new file mode 100644 index 00000000000..50751d4d7eb --- /dev/null +++ b/jaxp/test/TEST.groups @@ -0,0 +1,24 @@ +# 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. +# + +jaxp_all = \ + javax/xml/jaxp diff --git a/jaxws/.hgtags b/jaxws/.hgtags index defa79ac988..7e1244a3c4b 100644 --- a/jaxws/.hgtags +++ b/jaxws/.hgtags @@ -288,3 +288,5 @@ dd4ba422dba858b1c3c4b38f49a3e514be4e2790 jdk9-b38 5455969de31f3083bcfd779b7acc3ab758ecb308 jdk9-b40 4f785187377fe4c7ff388a7026dd72fcccdcfe7a jdk9-b41 301ddb4478fb36d1f025d14e7e48c2a434e9e6ff jdk9-b42 +edc13d27dc871be57d7ca77eef77e6d04972fee2 jdk9-b43 +2a03baa4d849818ff6d635f110c2813b12fc2326 jdk9-b44 diff --git a/jdk/.hgtags b/jdk/.hgtags index fa59d457917..bcf97a6c401 100644 --- a/jdk/.hgtags +++ b/jdk/.hgtags @@ -285,3 +285,5 @@ ca6edf957fe1c6ea818530b503578e872cea7239 jdk9-b39 f1ed1540da70a066527fd043413107e47721edbf jdk9-b40 e336cbd8b15e959e70ed02f0f5e93fa76ebd4c07 jdk9-b41 6b2314173433467245261364a52fb8e347fe6342 jdk9-b42 +8c6ad41974f9ab6c33d544b088648314963f2a50 jdk9-b43 +8cc4dc300041eb70a7a40e4b2431a8f4d4965ea4 jdk9-b44 diff --git a/jdk/make/src/classes/build/tools/module/boot.modules b/jdk/make/src/classes/build/tools/module/boot.modules index 396e13c4db3..9763b9287d4 100644 --- a/jdk/make/src/classes/build/tools/module/boot.modules +++ b/jdk/make/src/classes/build/tools/module/boot.modules @@ -17,10 +17,10 @@ java.security.sasl java.smartcardio java.sql java.sql.rowset +java.transaction java.xml java.xml.bind java.xml.crypto -java.xml.soap java.xml.ws jdk.charsets jdk.deploy diff --git a/jdk/src/java.base/share/classes/java/io/FilterOutputStream.java b/jdk/src/java.base/share/classes/java/io/FilterOutputStream.java index 7d5b0c9c074..85e4dd1b281 100644 --- a/jdk/src/java.base/share/classes/java/io/FilterOutputStream.java +++ b/jdk/src/java.base/share/classes/java/io/FilterOutputStream.java @@ -48,6 +48,8 @@ class FilterOutputStream extends OutputStream { */ protected OutputStream out; + private boolean closed; + /** * Creates an output stream filter built on top of the specified * underlying output stream. @@ -144,9 +146,9 @@ class FilterOutputStream extends OutputStream { * Closes this output stream and releases any system resources * associated with the stream. *

- * The close method of FilterOutputStream - * calls its flush method, and then calls the - * close method of its underlying output stream. + * When not already closed, the {@code close} method of {@code + * FilterOutputStream} calls its {@code flush} method, and then + * calls the {@code close} method of its underlying output stream. * * @exception IOException if an I/O error occurs. * @see java.io.FilterOutputStream#flush() @@ -154,6 +156,9 @@ class FilterOutputStream extends OutputStream { */ @SuppressWarnings("try") public void close() throws IOException { + if (closed) + return; + closed = true; try (OutputStream ostream = out) { flush(); } diff --git a/jdk/src/java.base/share/classes/java/lang/Deprecated.java b/jdk/src/java.base/share/classes/java/lang/Deprecated.java index 58a0691f054..7adc22edaf5 100644 --- a/jdk/src/java.base/share/classes/java/lang/Deprecated.java +++ b/jdk/src/java.base/share/classes/java/lang/Deprecated.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2015, 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 @@ -34,9 +34,13 @@ import static java.lang.annotation.ElementType.*; * or because a better alternative exists. Compilers warn when a * deprecated program element is used or overridden in non-deprecated code. * + *

Use of the @Deprecated annotation on a local variable + * declaration or on a parameter declaration or a package declaration + * has no effect. + * * @author Neal Gafter * @since 1.5 - * @jls 9.6.3.6 @Deprecated + * @jls 9.6.4.6 @Deprecated */ @Documented @Retention(RetentionPolicy.RUNTIME) diff --git a/jdk/src/java.base/share/classes/java/math/BigDecimal.java b/jdk/src/java.base/share/classes/java/math/BigDecimal.java index a42627d42c3..1ea1e8276c5 100644 --- a/jdk/src/java.base/share/classes/java/math/BigDecimal.java +++ b/jdk/src/java.base/share/classes/java/math/BigDecimal.java @@ -393,7 +393,7 @@ public class BigDecimal extends Number implements Comparable { *

Note that if the sequence of characters is already available * within a character array, using this constructor is faster than * converting the {@code char} array to string and using the - * {@code BigDecimal(String)} constructor . + * {@code BigDecimal(String)} constructor. * * @param in {@code char} array that is the source of characters. * @param offset first character in the array to inspect. @@ -466,7 +466,8 @@ public class BigDecimal extends Number implements Comparable { } else if (c == '.') { // have dot // have dot if (dot) // two dots - throw new NumberFormatException(); + throw new NumberFormatException("Character array" + + " contains more than one decimal point."); dot = true; } else if (Character.isDigit(c)) { // slow path int digit = Character.digit(c, 10); @@ -488,14 +489,16 @@ public class BigDecimal extends Number implements Comparable { exp = parseExp(in, offset, len); // Next test is required for backwards compatibility if ((int) exp != exp) // overflow - throw new NumberFormatException(); + throw new NumberFormatException("Exponent overflow."); break; // [saves a test] } else { - throw new NumberFormatException(); + throw new NumberFormatException("Character " + c + + " is neither a decimal digit number, decimal point, nor" + + " \"e\" notation exponential mark."); } } if (prec == 0) // no digits found - throw new NumberFormatException(); + throw new NumberFormatException("No digits found."); // Adjust scale if exp is not zero. if (exp != 0) { // had significant exponent scl = adjustScale(scl, exp); @@ -541,22 +544,24 @@ public class BigDecimal extends Number implements Comparable { if (c == '.') { // have dot if (dot) // two dots - throw new NumberFormatException(); + throw new NumberFormatException("Character array" + + " contains more than one decimal point."); dot = true; continue; } // exponent expected if ((c != 'e') && (c != 'E')) - throw new NumberFormatException(); + throw new NumberFormatException("Character array" + + " is missing \"e\" notation exponential mark."); exp = parseExp(in, offset, len); // Next test is required for backwards compatibility if ((int) exp != exp) // overflow - throw new NumberFormatException(); + throw new NumberFormatException("Exponent overflow."); break; // [saves a test] } // here when no characters left if (prec == 0) // no digits found - throw new NumberFormatException(); + throw new NumberFormatException("No digits found."); // Adjust scale if exp is not zero. if (exp != 0) { // had significant exponent scl = adjustScale(scl, exp); @@ -592,10 +597,10 @@ public class BigDecimal extends Number implements Comparable { } } } - } catch (ArrayIndexOutOfBoundsException e) { - throw new NumberFormatException(); - } catch (NegativeArraySizeException e) { - throw new NumberFormatException(); + } catch (ArrayIndexOutOfBoundsException | NegativeArraySizeException e) { + NumberFormatException nfe = new NumberFormatException(); + nfe.initCause(e); + throw nfe; } this.scale = scl; this.precision = prec; @@ -627,7 +632,7 @@ public class BigDecimal extends Number implements Comparable { len--; } if (len <= 0) // no exponent digits - throw new NumberFormatException(); + throw new NumberFormatException("No exponent digits."); // skip leading zeros in the exponent while (len > 10 && (c=='0' || (Character.digit(c, 10) == 0))) { offset++; @@ -635,7 +640,7 @@ public class BigDecimal extends Number implements Comparable { len--; } if (len > 10) // too many nonzero exponent digits - throw new NumberFormatException(); + throw new NumberFormatException("Too many nonzero exponent digits."); // c now holds first digit of exponent for (;; len--) { int v; @@ -644,7 +649,7 @@ public class BigDecimal extends Number implements Comparable { } else { v = Character.digit(c, 10); if (v < 0) // not a digit - throw new NumberFormatException(); + throw new NumberFormatException("Not a digit."); } exp = exp * 10 + v; if (len == 1) diff --git a/jdk/src/java.base/share/classes/java/util/Formatter.java b/jdk/src/java.base/share/classes/java/util/Formatter.java index 70298d5b59f..a973ee6889e 100644 --- a/jdk/src/java.base/share/classes/java/util/Formatter.java +++ b/jdk/src/java.base/share/classes/java/util/Formatter.java @@ -3727,29 +3727,29 @@ public final class Formatter implements Closeable, Flushable { exp = new StringBuilder("+00"); } } - return; - } - long adjusted = -(long) scale + (len - 1); - if (form == BigDecimalLayoutForm.DECIMAL_FLOAT) { + } else if (form == BigDecimalLayoutForm.DECIMAL_FLOAT) { // count of padding zeros - int pad = scale - len; - if (pad >= 0) { + + if (scale >= len) { // 0.xxx form mant.append("0."); dot = true; - trailingZeros(mant, pad); + trailingZeros(mant, scale - len); mant.append(coeff); } else { - if (-pad < len) { + if (scale > 0) { // xx.xx form - mant.append(coeff, 0, -pad); + int pad = len - scale; + mant.append(coeff, 0, pad); mant.append('.'); dot = true; - mant.append(coeff, -pad, -pad + scale); - } else { + mant.append(coeff, pad, len); + } else { // scale < 0 // xx form mant.append(coeff, 0, len); - trailingZeros(mant, -scale); + if (intVal.signum() != 0) { + trailingZeros(mant, -scale); + } this.scale = 0; } } @@ -3762,6 +3762,7 @@ public final class Formatter implements Closeable, Flushable { mant.append(coeff, 1, len); } exp = new StringBuilder(); + long adjusted = -(long) scale + (len - 1); if (adjusted != 0) { long abs = Math.abs(adjusted); // require sign diff --git a/jdk/src/java.base/share/classes/javax/crypto/spec/RC5ParameterSpec.java b/jdk/src/java.base/share/classes/javax/crypto/spec/RC5ParameterSpec.java index 0eddb61f1de..5d8f09f4567 100644 --- a/jdk/src/java.base/share/classes/javax/crypto/spec/RC5ParameterSpec.java +++ b/jdk/src/java.base/share/classes/javax/crypto/spec/RC5ParameterSpec.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2015, 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 @@ -29,7 +29,7 @@ import java.security.spec.AlgorithmParameterSpec; /** * This class specifies the parameters used with the - * RC5 + * RC5 * algorithm. * *

The parameters consist of a version number, a rounds count, a word @@ -37,7 +37,7 @@ import java.security.spec.AlgorithmParameterSpec; * *

This class can be used to initialize a Cipher object that * implements the RC5 algorithm as supplied by - * RSA Security Inc., + * RSA Security LLC, * or any parties authorized by RSA Security. * * @author Jan Luehe diff --git a/jdk/src/java.base/share/classes/sun/security/provider/DSA.java b/jdk/src/java.base/share/classes/sun/security/provider/DSA.java index 641c719b26a..66b83ad83bc 100644 --- a/jdk/src/java.base/share/classes/sun/security/provider/DSA.java +++ b/jdk/src/java.base/share/classes/sun/security/provider/DSA.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 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 @@ -117,7 +117,6 @@ abstract class DSA extends SignatureSpi { if (params == null) { throw new InvalidKeyException("DSA private key lacks parameters"); } - checkKey(params); this.params = params; this.presetX = priv.getX(); @@ -149,7 +148,6 @@ abstract class DSA extends SignatureSpi { if (params == null) { throw new InvalidKeyException("DSA public key lacks parameters"); } - checkKey(params); this.params = params; this.presetY = pub.getY(); @@ -291,16 +289,6 @@ abstract class DSA extends SignatureSpi { return null; } - protected void checkKey(DSAParams params) throws InvalidKeyException { - // FIPS186-3 states in sec4.2 that a hash function which provides - // a lower security strength than the (L, N) pair ordinarily should - // not be used. - int valueN = params.getQ().bitLength(); - if (valueN > md.getDigestLength()*8) { - throw new InvalidKeyException("Key is too strong for this signature algorithm"); - } - } - private BigInteger generateR(BigInteger p, BigInteger q, BigInteger g, BigInteger k) { BigInteger temp = g.modPow(k, p); @@ -480,14 +468,6 @@ abstract class DSA extends SignatureSpi { } } - @Override - protected void checkKey(DSAParams params) throws InvalidKeyException { - int valueL = params.getP().bitLength(); - if (valueL > 1024) { - throw new InvalidKeyException("Key is too long for this algorithm"); - } - } - /* * Please read bug report 4044247 for an alternative, faster, * NON-FIPS approved method to generate K diff --git a/jdk/src/java.base/share/native/libzip/Deflater.c b/jdk/src/java.base/share/native/libzip/Deflater.c index d7f751d37a9..7492a082170 100644 --- a/jdk/src/java.base/share/native/libzip/Deflater.c +++ b/jdk/src/java.base/share/native/libzip/Deflater.c @@ -76,10 +76,11 @@ Java_java_util_zip_Deflater_init(JNIEnv *env, jclass cls, jint level, JNU_ThrowOutOfMemoryError(env, 0); return jlong_zero; } else { - char *msg; - switch (deflateInit2(strm, level, Z_DEFLATED, - nowrap ? -MAX_WBITS : MAX_WBITS, - DEF_MEM_LEVEL, strategy)) { + const char *msg; + int ret = deflateInit2(strm, level, Z_DEFLATED, + nowrap ? -MAX_WBITS : MAX_WBITS, + DEF_MEM_LEVEL, strategy); + switch (ret) { case Z_OK: return ptr_to_jlong(strm); case Z_MEM_ERROR: @@ -91,7 +92,11 @@ Java_java_util_zip_Deflater_init(JNIEnv *env, jclass cls, jint level, JNU_ThrowIllegalArgumentException(env, 0); return jlong_zero; default: - msg = strm->msg; + msg = ((strm->msg != NULL) ? strm->msg : + (ret == Z_VERSION_ERROR) ? + "zlib returned Z_VERSION_ERROR: " + "compile time and runtime zlib implementations differ" : + "unknown error initializing zlib library"); free(strm); JNU_ThrowInternalError(env, msg); return jlong_zero; diff --git a/jdk/src/java.base/windows/classes/sun/nio/ch/FileDispatcherImpl.java b/jdk/src/java.base/windows/classes/sun/nio/ch/FileDispatcherImpl.java index c767a34cc08..a8c20e2bb58 100644 --- a/jdk/src/java.base/windows/classes/sun/nio/ch/FileDispatcherImpl.java +++ b/jdk/src/java.base/windows/classes/sun/nio/ch/FileDispatcherImpl.java @@ -123,7 +123,7 @@ class FileDispatcherImpl extends FileDispatcher { new PrivilegedAction() { @Override public String run() { - return System.getProperty("jdk.net.enableFastFileTransfer"); + return System.getProperty("jdk.nio.enableFastFileTransfer"); } }); boolean enable; diff --git a/jdk/src/java.base/windows/native/libnet/NetworkInterface_winXP.c b/jdk/src/java.base/windows/native/libnet/NetworkInterface_winXP.c index e5580c6f3dc..2308a59b44b 100644 --- a/jdk/src/java.base/windows/native/libnet/NetworkInterface_winXP.c +++ b/jdk/src/java.base/windows/native/libnet/NetworkInterface_winXP.c @@ -81,9 +81,17 @@ static int getAdapters (JNIEnv *env, IP_ADAPTER_ADDRESSES **adapters) { DWORD ret, flags; IP_ADAPTER_ADDRESSES *adapterInfo; ULONG len; + char *error_msg_buf = NULL; + size_t error_msg_buf_size = + strlen("IP Helper Library GetAdaptersAddresses function failed" + " with error == ") + 10; + int _ret = 0; + + adapterInfo = (IP_ADAPTER_ADDRESSES *)malloc (bufsize); if (adapterInfo == NULL) { - JNU_ThrowByName(env, "java/lang/OutOfMemoryError", "Native heap allocation failure"); + JNU_ThrowByName(env, "java/lang/OutOfMemoryError", + "Native heap allocation failure"); return -1; } @@ -94,10 +102,12 @@ static int getAdapters (JNIEnv *env, IP_ADAPTER_ADDRESSES **adapters) { ret = GetAdaptersAddresses(AF_UNSPEC, flags, NULL, adapterInfo, &len); if (ret == ERROR_BUFFER_OVERFLOW) { - IP_ADAPTER_ADDRESSES * newAdapterInfo = (IP_ADAPTER_ADDRESSES *) realloc (adapterInfo, len); + IP_ADAPTER_ADDRESSES * newAdapterInfo = + (IP_ADAPTER_ADDRESSES *) realloc (adapterInfo, len); if (newAdapterInfo == NULL) { free(adapterInfo); - JNU_ThrowByName(env, "java/lang/OutOfMemoryError", "Native heap allocation failure"); + JNU_ThrowByName(env, "java/lang/OutOfMemoryError", + "Native heap allocation failure"); return -1; } @@ -109,8 +119,32 @@ static int getAdapters (JNIEnv *env, IP_ADAPTER_ADDRESSES **adapters) { if (ret != ERROR_SUCCESS) { free (adapterInfo); - JNU_ThrowByName(env, "java/lang/Error", - "IP Helper Library GetAdaptersAddresses function failed"); + if (ret == ERROR_INSUFFICIENT_BUFFER) { + JNU_ThrowByName(env, "java/lang/Error", + "IP Helper Library GetAdaptersAddresses function failed " + "with ERROR_INSUFFICIENT_BUFFER"); + } else if (ret == ERROR_ADDRESS_NOT_ASSOCIATED ) { + JNU_ThrowByName(env, "java/lang/Error", + "IP Helper Library GetAdaptersAddresses function failed " + "with ERROR_ADDRESS_NOT_ASSOCIATED"); + } else { + error_msg_buf = (char *)malloc(error_msg_buf_size); + if (error_msg_buf != NULL) { + memset(error_msg_buf, 0, error_msg_buf_size); + _ret = _snprintf_s(error_msg_buf, error_msg_buf_size, + _TRUNCATE, "IP Helper Library GetAdaptersAddresses " + "function failed with error == %d", ret); + if (_ret != -1) { + JNU_ThrowByName(env, "java/lang/Error", error_msg_buf); + } else { + JNU_ThrowByName(env, "java/lang/Error", + "IP Helper Library GetAdaptersAddresses function failure"); + } + } else { + JNU_ThrowByName(env, "java/lang/Error", + "IP Helper Library GetAdaptersAddresses function failed"); + } + } return -1; } *adapters = adapterInfo; @@ -126,9 +160,14 @@ IP_ADAPTER_ADDRESSES *getAdapter (JNIEnv *env, jint index) { DWORD flags, val; IP_ADAPTER_ADDRESSES *adapterInfo, *ptr, *ret; ULONG len; + char *error_msg_buf = NULL; + size_t error_msg_buf_size = + strlen("IP Helper Library GetAdaptersAddresses function failed with error == ") + 10; + int _ret = 0; adapterInfo = (IP_ADAPTER_ADDRESSES *)malloc (bufsize); if (adapterInfo == NULL) { - JNU_ThrowByName(env, "java/lang/OutOfMemoryError", "Native heap allocation failure"); + JNU_ThrowByName(env, "java/lang/OutOfMemoryError", + "Native heap allocation failure"); return NULL; } len = bufsize; @@ -137,10 +176,12 @@ IP_ADAPTER_ADDRESSES *getAdapter (JNIEnv *env, jint index) { flags |= GAA_FLAG_INCLUDE_PREFIX; val = GetAdaptersAddresses(AF_UNSPEC, flags, NULL, adapterInfo, &len); if (val == ERROR_BUFFER_OVERFLOW) { - IP_ADAPTER_ADDRESSES * newAdapterInfo = (IP_ADAPTER_ADDRESSES *) realloc (adapterInfo, len); + IP_ADAPTER_ADDRESSES * newAdapterInfo = + (IP_ADAPTER_ADDRESSES *) realloc (adapterInfo, len); if (newAdapterInfo == NULL) { free(adapterInfo); - JNU_ThrowByName(env, "java/lang/OutOfMemoryError", "Native heap allocation failure"); + JNU_ThrowByName(env, "java/lang/OutOfMemoryError", + "Native heap allocation failure"); return NULL; } @@ -152,10 +193,35 @@ IP_ADAPTER_ADDRESSES *getAdapter (JNIEnv *env, jint index) { if (val != ERROR_SUCCESS) { free (adapterInfo); - JNU_ThrowByName(env, "java/lang/Error", - "IP Helper Library GetAdaptersAddresses function failed"); + if (val == ERROR_INSUFFICIENT_BUFFER) { + JNU_ThrowByName(env, "java/lang/Error", + "IP Helper Library GetAdaptersAddresses function failed " + "with ERROR_INSUFFICIENT_BUFFER"); + } else if (val == ERROR_ADDRESS_NOT_ASSOCIATED ) { + JNU_ThrowByName(env, "java/lang/Error", + "IP Helper Library GetAdaptersAddresses function failed " + "with ERROR_ADDRESS_NOT_ASSOCIATED"); + } else { + error_msg_buf = (char *)malloc(error_msg_buf_size); + if (error_msg_buf != NULL) { + memset(error_msg_buf, 0, error_msg_buf_size); + _ret = _snprintf_s(error_msg_buf, error_msg_buf_size, + _TRUNCATE, "IP Helper Library GetAdaptersAddresses function failed " + "with error == %d", val); + if (_ret != -1) { + JNU_ThrowByName(env, "java/lang/Error", error_msg_buf); + } else { + JNU_ThrowByName(env, "java/lang/Error", + "IP Helper Library GetAdaptersAddresses function failure"); + } + } else { + JNU_ThrowByName(env, "java/lang/Error", + "IP Helper Library GetAdaptersAddresses function failed"); + } + } return NULL; } + ptr = adapterInfo; ret = NULL; while (ptr != NULL) { @@ -168,7 +234,8 @@ IP_ADAPTER_ADDRESSES *getAdapter (JNIEnv *env, jint index) { ret = (IP_ADAPTER_ADDRESSES *) malloc(sizeof(IP_ADAPTER_ADDRESSES)); if (ret == NULL) { free(adapterInfo); - JNU_ThrowByName(env, "java/lang/OutOfMemoryError", "Native heap allocation failure"); + JNU_ThrowByName(env, "java/lang/OutOfMemoryError", + "Native heap allocation failure"); return NULL; } diff --git a/jdk/src/java.scripting/share/classes/javax/script/ScriptEngineFactory.java b/jdk/src/java.scripting/share/classes/javax/script/ScriptEngineFactory.java index e73c99f5203..7692a0aaec7 100644 --- a/jdk/src/java.scripting/share/classes/javax/script/ScriptEngineFactory.java +++ b/jdk/src/java.scripting/share/classes/javax/script/ScriptEngineFactory.java @@ -85,7 +85,7 @@ public interface ScriptEngineFactory { public List getNames(); /** - * Returns the name of the scripting langauge supported by this + * Returns the name of the scripting language supported by this * ScriptEngine. * @return The name of the supported language. */ @@ -104,14 +104,15 @@ public interface ScriptEngineFactory { *

    *
  • ScriptEngine.ENGINE
  • *
  • ScriptEngine.ENGINE_VERSION
  • - *
  • ScriptEngine.NAME
  • *
  • ScriptEngine.LANGUAGE
  • *
  • ScriptEngine.LANGUAGE_VERSION
  • + *
  • ScriptEngine.NAME
  • *
*

* The values for these keys are the Strings returned by getEngineName, - * getEngineVersion, getName, getLanguageName and - * getLanguageVersion respectively.

+ * getEngineVersion, getLanguageName, + * getLanguageVersion for the first four keys respectively. For NAME, one of the Strings + * returned by getNames is returned.

* A reserved key, THREADING, whose value describes the behavior of the engine * with respect to concurrent execution of scripts and maintenance of state is also defined. * These values for the THREADING key are:

diff --git a/jdk/src/java.sql/share/classes/javax/transaction/xa/XAException.java b/jdk/src/java.sql/share/classes/javax/transaction/xa/XAException.java new file mode 100644 index 00000000000..62ae7e5e8d9 --- /dev/null +++ b/jdk/src/java.sql/share/classes/javax/transaction/xa/XAException.java @@ -0,0 +1,196 @@ +/* + * Copyright (c) 2000, 2001, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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. + */ + +package javax.transaction.xa; + +/** + * The XAException is thrown by the Resource Manager (RM) to inform the + * Transaction Manager of an error encountered by the involved transaction. + * + */ +public class XAException extends Exception { + //private static final long serialVersionUID = -8249683284832867751L; + + /** + * The error code with which to create the SystemException. + * + * @serial The error code for the exception + */ + public int errorCode; + + /** + * Create an XAException. + */ + public XAException() { + super(); + } + + /** + * Create an XAException with a given string. + * + * @param s The String object containing the exception + * message. + */ + public XAException(String s) { + super(s); + } + + /** + * Create an XAException with a given error code. + * + * @param errcode The error code identifying the exception. + */ + public XAException(int errcode) { + super(); + errorCode = errcode; + } + + /** + * The inclusive lower bound of the rollback codes. + */ + public final static int XA_RBBASE = 100; + + /** + * Indicates that the rollback was caused by an unspecified reason. + */ + public final static int XA_RBROLLBACK = XA_RBBASE; + + /** + * Indicates that the rollback was caused by a communication failure. + */ + public final static int XA_RBCOMMFAIL = XA_RBBASE + 1; + + /** + * A deadlock was detected. + */ + public final static int XA_RBDEADLOCK = XA_RBBASE + 2; + + /** + * A condition that violates the integrity of the resource was detected. + */ + public final static int XA_RBINTEGRITY = XA_RBBASE + 3; + + /** + * The resource manager rolled back the transaction branch for a reason + * not on this list. + */ + public final static int XA_RBOTHER = XA_RBBASE + 4; + + /** + * A protocol error occurred in the resource manager. + */ + public final static int XA_RBPROTO = XA_RBBASE + 5; + + /** + * A transaction branch took too long. + */ + public final static int XA_RBTIMEOUT = XA_RBBASE + 6; + + /** + * May retry the transaction branch. + */ + public final static int XA_RBTRANSIENT = XA_RBBASE + 7; + + /** + * The inclusive upper bound of the rollback error code. + */ + public final static int XA_RBEND = XA_RBTRANSIENT; + + /** + * Resumption must occur where the suspension occurred. + */ + public final static int XA_NOMIGRATE = 9; + + /** + * The transaction branch may have been heuristically completed. + */ + public final static int XA_HEURHAZ = 8; + + /** + * The transaction branch has been heuristically committed. + */ + public final static int XA_HEURCOM = 7; + + /** + * The transaction branch has been heuristically rolled back. + */ + public final static int XA_HEURRB = 6; + + /** + * The transaction branch has been heuristically committed and + * rolled back. + */ + public final static int XA_HEURMIX = 5; + + /** + * Routine returned with no effect and may be reissued. + */ + public final static int XA_RETRY = 4; + + /** + * The transaction branch was read-only and has been committed. + */ + public final static int XA_RDONLY = 3; + + /** + * There is an asynchronous operation already outstanding. + */ + public final static int XAER_ASYNC = -2; + + /** + * A resource manager error has occurred in the transaction branch. + */ + public final static int XAER_RMERR = -3; + + /** + * The XID is not valid. + */ + public final static int XAER_NOTA = -4; + + /** + * Invalid arguments were given. + */ + public final static int XAER_INVAL = -5; + + /** + * Routine was invoked in an inproper context. + */ + public final static int XAER_PROTO = -6; + + /** + * Resource manager is unavailable. + */ + public final static int XAER_RMFAIL = -7; + + /** + * The XID already exists. + */ + public final static int XAER_DUPID = -8; + + /** + * The resource manager is doing work outside a global transaction. + */ + public final static int XAER_OUTSIDE = -9; +} diff --git a/jdk/src/java.sql/share/classes/javax/transaction/xa/XAResource.java b/jdk/src/java.sql/share/classes/javax/transaction/xa/XAResource.java new file mode 100644 index 00000000000..489818e98a5 --- /dev/null +++ b/jdk/src/java.sql/share/classes/javax/transaction/xa/XAResource.java @@ -0,0 +1,305 @@ +/* + * Copyright (c) 2000, 2001, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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. + */ + +package javax.transaction.xa; + +/** + * The XAResource interface is a Java mapping of the industry standard + * XA interface based on the X/Open CAE Specification (Distributed + * Transaction Processing: The XA Specification). + * + *

The XA interface defines the contract between a Resource Manager + * and a Transaction Manager in a distributed transaction processing + * (DTP) environment. A JDBC driver or a JMS provider implements + * this interface to support the association between a global transaction + * and a database or message service connection. + * + *

The XAResource interface can be supported by any transactional + * resource that is intended to be used by application programs in an + * environment where transactions are controlled by an external + * transaction manager. An example of such a resource is a database + * management system. An application may access data through multiple + * database connections. Each database connection is enlisted with + * the transaction manager as a transactional resource. The transaction + * manager obtains an XAResource for each connection participating + * in a global transaction. The transaction manager uses the + * start method + * to associate the global transaction with the resource, and it uses the + * end method to disassociate the transaction from + * the resource. The resource + * manager is responsible for associating the global transaction to all + * work performed on its data between the start and end method invocations. + * + *

At transaction commit time, the resource managers are informed by + * the transaction manager to prepare, commit, or rollback a transaction + * according to the two-phase commit protocol.

+ * + */ +public interface XAResource { + + /** + * Commits the global transaction specified by xid. + * + * @param xid A global transaction identifier + * + * @param onePhase If true, the resource manager should use a one-phase + * commit protocol to commit the work done on behalf of xid. + * + * @exception XAException An error has occurred. Possible XAExceptions + * are XA_HEURHAZ, XA_HEURCOM, XA_HEURRB, XA_HEURMIX, XAER_RMERR, + * XAER_RMFAIL, XAER_NOTA, XAER_INVAL, or XAER_PROTO. + * + *

If the resource manager did not commit the transaction and the + * paramether onePhase is set to true, the resource manager may throw + * one of the XA_RB* exceptions. Upon return, the resource manager has + * rolled back the branch's work and has released all held resources. + */ + void commit(Xid xid, boolean onePhase) throws XAException; + + /** + * Ends the work performed on behalf of a transaction branch. + * The resource manager disassociates the XA resource from the + * transaction branch specified and lets the transaction + * complete. + * + *

If TMSUSPEND is specified in the flags, the transaction branch + * is temporarily suspended in an incomplete state. The transaction + * context is in a suspended state and must be resumed via the + * start method with TMRESUME specified.

+ * + *

If TMFAIL is specified, the portion of work has failed. + * The resource manager may mark the transaction as rollback-only

+ * + *

If TMSUCCESS is specified, the portion of work has completed + * successfully.

+ * + * @param xid A global transaction identifier that is the same as + * the identifier used previously in the start method. + * + * @param flags One of TMSUCCESS, TMFAIL, or TMSUSPEND. + * + * @exception XAException An error has occurred. Possible XAException + * values are XAER_RMERR, XAER_RMFAILED, XAER_NOTA, XAER_INVAL, + * XAER_PROTO, or XA_RB*. + */ + void end(Xid xid, int flags) throws XAException; + + /** + * Tells the resource manager to forget about a heuristically + * completed transaction branch. + * + * @param xid A global transaction identifier. + * + * @exception XAException An error has occurred. Possible exception + * values are XAER_RMERR, XAER_RMFAIL, XAER_NOTA, XAER_INVAL, or + * XAER_PROTO. + */ + void forget(Xid xid) throws XAException; + + /** + * Obtains the current transaction timeout value set for this + * XAResource instance. If XAResource.setTransactionTimeout + * was not used prior to invoking this method, the return value + * is the default timeout set for the resource manager; otherwise, + * the value used in the previous setTransactionTimeout + * call is returned. + * + * @return the transaction timeout value in seconds. + * + * @exception XAException An error has occurred. Possible exception + * values are XAER_RMERR and XAER_RMFAIL. + */ + int getTransactionTimeout() throws XAException; + + /** + * This method is called to determine if the resource manager + * instance represented by the target object is the same as the + * resouce manager instance represented by the parameter xares. + * + * @param xares An XAResource object whose resource manager instance + * is to be compared with the resource manager instance of the + * target object. + * + * @return true if it's the same RM instance; otherwise + * false. + * + * @exception XAException An error has occurred. Possible exception + * values are XAER_RMERR and XAER_RMFAIL. + */ + boolean isSameRM(XAResource xares) throws XAException; + + /** + * Ask the resource manager to prepare for a transaction commit + * of the transaction specified in xid. + * + * @param xid A global transaction identifier. + * + * @exception XAException An error has occurred. Possible exception + * values are: XA_RB*, XAER_RMERR, XAER_RMFAIL, XAER_NOTA, XAER_INVAL, + * or XAER_PROTO. + * + * @return A value indicating the resource manager's vote on the + * outcome of the transaction. The possible values are: XA_RDONLY + * or XA_OK. If the resource manager wants to roll back the + * transaction, it should do so by raising an appropriate XAException + * in the prepare method. + */ + int prepare(Xid xid) throws XAException; + + /** + * Obtains a list of prepared transaction branches from a resource + * manager. The transaction manager calls this method during recovery + * to obtain the list of transaction branches that are currently in + * prepared or heuristically completed states. + * + * @param flag One of TMSTARTRSCAN, TMENDRSCAN, TMNOFLAGS. TMNOFLAGS + * must be used when no other flags are set in the parameter. + * + * @exception XAException An error has occurred. Possible values are + * XAER_RMERR, XAER_RMFAIL, XAER_INVAL, and XAER_PROTO. + * + * @return The resource manager returns zero or more XIDs of the + * transaction branches that are currently in a prepared or + * heuristically completed state. If an error occurs during the + * operation, the resource manager should throw the appropriate + * XAException. + */ + Xid[] recover(int flag) throws XAException; + + /** + * Informs the resource manager to roll back work done on behalf + * of a transaction branch. + * + * @param xid A global transaction identifier. + * + * @exception XAException An error has occurred. + */ + void rollback(Xid xid) throws XAException; + + /** + * Sets the current transaction timeout value for this XAResource + * instance. Once set, this timeout value is effective until + * setTransactionTimeout is invoked again with a different + * value. To reset the timeout value to the default value used by the resource + * manager, set the value to zero. + * + * If the timeout operation is performed successfully, the method returns + * true; otherwise false. If a resource manager does not + * support explicitly setting the transaction timeout value, this method + * returns false. + * + * @param seconds The transaction timeout value in seconds. + * + * @return true if the transaction timeout value is set successfully; + * otherwise false. + * + * @exception XAException An error has occurred. Possible exception values + * are XAER_RMERR, XAER_RMFAIL, or XAER_INVAL. + */ + boolean setTransactionTimeout(int seconds) throws XAException; + + /** + * Starts work on behalf of a transaction branch specified in + * xid. + * + * If TMJOIN is specified, the start applies to joining a transaction + * previously seen by the resource manager. If TMRESUME is specified, + * the start applies to resuming a suspended transaction specified in the + * parameter xid. + * + * If neither TMJOIN nor TMRESUME is specified and the transaction + * specified by xid has previously been seen by the resource + * manager, the resource manager throws the XAException exception with + * XAER_DUPID error code. + * + * @param xid A global transaction identifier to be associated + * with the resource. + * + * @param flags One of TMNOFLAGS, TMJOIN, or TMRESUME. + * + * @exception XAException An error has occurred. Possible exceptions + * are XA_RB*, XAER_RMERR, XAER_RMFAIL, XAER_DUPID, XAER_OUTSIDE, + * XAER_NOTA, XAER_INVAL, or XAER_PROTO. + */ + void start(Xid xid, int flags) throws XAException; + + /** + * Ends a recovery scan. + */ + public final static int TMENDRSCAN = 0x00800000; + + /** + * Disassociates the caller and marks the transaction branch + * rollback-only. + */ + public final static int TMFAIL = 0x20000000; + + /** + * Caller is joining existing transaction branch. + */ + public final static int TMJOIN = 0x00200000; + + /** + * Use TMNOFLAGS to indicate no flags value is selected. + */ + public final static int TMNOFLAGS = 0x00000000; + + /** + * Caller is using one-phase optimization. + */ + public final static int TMONEPHASE = 0x40000000; + + /** + * Caller is resuming association with a suspended + * transaction branch. + */ + public final static int TMRESUME = 0x08000000; + + /** + * Starts a recovery scan. + */ + public final static int TMSTARTRSCAN = 0x01000000; + + /** + * Disassociates caller from a transaction branch. + */ + public final static int TMSUCCESS = 0x04000000; + + /** + * Caller is suspending (not ending) its association with + * a transaction branch. + */ + public final static int TMSUSPEND = 0x02000000; + + /** + * The transaction branch has been read-only and has been committed. + */ + public final static int XA_RDONLY = 0x00000003; + + /** + * The transaction work has been prepared normally. + */ + public final static int XA_OK = 0; +} diff --git a/jdk/src/java.sql/share/classes/javax/transaction/xa/Xid.java b/jdk/src/java.sql/share/classes/javax/transaction/xa/Xid.java new file mode 100644 index 00000000000..829ae685e80 --- /dev/null +++ b/jdk/src/java.sql/share/classes/javax/transaction/xa/Xid.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2000, 2002, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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. + */ + +package javax.transaction.xa; + +/** + * The Xid interface is a Java mapping of the X/Open transaction identifier + * XID structure. This interface specifies three accessor methods to + * retrieve a global transaction format ID, global transaction ID, + * and branch qualifier. The Xid interface is used by the transaction + * manager and the resource managers. This interface is not visible to + * the application programs. + */ +public interface Xid { + + /** + * Maximum number of bytes returned by getGtrid. + */ + final static int MAXGTRIDSIZE = 64; + + /** + * Maximum number of bytes returned by getBqual. + */ + final static int MAXBQUALSIZE = 64; + + /** + * Obtain the format identifier part of the XID. + * + * @return Format identifier. O means the OSI CCR format. + */ + int getFormatId(); + + /** + * Obtain the global transaction identifier part of XID as an array + * of bytes. + * + * @return Global transaction identifier. + */ + byte[] getGlobalTransactionId(); + + /** + * Obtain the transaction branch identifier part of XID as an array + * of bytes. + * + * @return Global transaction identifier. + */ + byte[] getBranchQualifier(); +} diff --git a/jdk/src/java.sql/share/classes/javax/transaction/xa/package.html b/jdk/src/java.sql/share/classes/javax/transaction/xa/package.html new file mode 100644 index 00000000000..daa9e6807ca --- /dev/null +++ b/jdk/src/java.sql/share/classes/javax/transaction/xa/package.html @@ -0,0 +1,41 @@ + + + + + + + + +Provides the API that defines the contract between the transaction +manager and the resource manager, which allows the transaction +manager to enlist and delist resource objects (supplied by the +resource manager driver) in JTA transactions. The driver vendor +for a specific resource manager provides the implementation of +this API. +

+@since 1.4 + + diff --git a/jdk/src/java.transaction/share/classes/javax/transaction/InvalidTransactionException.java b/jdk/src/java.transaction/share/classes/javax/transaction/InvalidTransactionException.java new file mode 100644 index 00000000000..5d0c699b887 --- /dev/null +++ b/jdk/src/java.transaction/share/classes/javax/transaction/InvalidTransactionException.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 1998, 1999, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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. + */ +/* + * Licensed Materials - Property of IBM + * RMI-IIOP v1.0 + * Copyright IBM Corp. 1998 1999 All Rights Reserved + * + */ + +package javax.transaction; + +/** + * This exception indicates that the request carried an invalid transaction + * context. For example, this exception could be raised if an error + * occured when trying to register a resource. + */ +@SuppressWarnings("serial") // serialVersionUID intentionally omitted +public class InvalidTransactionException extends java.rmi.RemoteException { + + public InvalidTransactionException() { + super(); + } + + public InvalidTransactionException(String msg) { + super(msg); + } +} diff --git a/jdk/src/java.transaction/share/classes/javax/transaction/TransactionRequiredException.java b/jdk/src/java.transaction/share/classes/javax/transaction/TransactionRequiredException.java new file mode 100644 index 00000000000..ee2ccbb8040 --- /dev/null +++ b/jdk/src/java.transaction/share/classes/javax/transaction/TransactionRequiredException.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 1998, 1999, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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. + */ +/* + * Licensed Materials - Property of IBM + * RMI-IIOP v1.0 + * Copyright IBM Corp. 1998 1999 All Rights Reserved + * + */ + +package javax.transaction; + +/** + * This exception indicates that a request carried a null transaction context, + * but the target object requires an activate transaction. + */ +@SuppressWarnings("serial") // serialVersionUID intentionally omitted +public class TransactionRequiredException extends java.rmi.RemoteException { + + public TransactionRequiredException() { + super(); + } + + public TransactionRequiredException(String msg) { + super(msg); + } +} diff --git a/jdk/src/java.transaction/share/classes/javax/transaction/TransactionRolledbackException.java b/jdk/src/java.transaction/share/classes/javax/transaction/TransactionRolledbackException.java new file mode 100644 index 00000000000..73ee335beee --- /dev/null +++ b/jdk/src/java.transaction/share/classes/javax/transaction/TransactionRolledbackException.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 1998, 1999, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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. + */ +/* + * Licensed Materials - Property of IBM + * RMI-IIOP v1.0 + * Copyright IBM Corp. 1998 1999 All Rights Reserved + * + */ + +package javax.transaction; + +/** + * This exception indicates that the transaction associated with processing + * of the request has been rolled back, or marked to roll back. Thus the + * requested operation either could not be performed or was not performed + * because further computation on behalf of the transaction would be + * fruitless + */ +@SuppressWarnings("serial") // serialVersionUID intentionally omitted +public class TransactionRolledbackException extends java.rmi.RemoteException { + + public TransactionRolledbackException() { + super(); + } + + public TransactionRolledbackException(String msg) { + super(msg); + } +} diff --git a/jdk/src/java.transaction/share/classes/javax/transaction/package.html b/jdk/src/java.transaction/share/classes/javax/transaction/package.html new file mode 100644 index 00000000000..7f71b1791c8 --- /dev/null +++ b/jdk/src/java.transaction/share/classes/javax/transaction/package.html @@ -0,0 +1,36 @@ + + + + + + + + +Contains three exceptions thrown by the ORB machinery during unmarshalling. +

+@since 1.3 + + diff --git a/jdk/src/jdk.jvmstat/share/classes/sun/jvmstat/perfdata/monitor/AliasFileParser.java b/jdk/src/jdk.jvmstat/share/classes/sun/jvmstat/perfdata/monitor/AliasFileParser.java index aabe4dabb5b..3a4134bc6f9 100644 --- a/jdk/src/jdk.jvmstat/share/classes/sun/jvmstat/perfdata/monitor/AliasFileParser.java +++ b/jdk/src/jdk.jvmstat/share/classes/sun/jvmstat/perfdata/monitor/AliasFileParser.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 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,7 @@ import java.util.regex.*; */ public class AliasFileParser { private static final String ALIAS = "alias"; - private static final boolean DEBUG = false; + // 8028357 removed old, inefficient debug logging // other variables private URL inputfile; @@ -64,21 +64,12 @@ public class AliasFileParser { } } - private void logln(String s) { - if (DEBUG) { - System.err.println(s); - } - } - /** * method to get the next token as a Token type */ private void nextToken() throws IOException { st.nextToken(); currentToken = new Token(st.ttype, st.sval); - - logln("Read token: type = " + currentToken.ttype - + " string = " + currentToken.sval); } /** @@ -90,8 +81,6 @@ public class AliasFileParser { if ((currentToken.ttype == ttype) && (currentToken.sval.compareTo(token) == 0)) { - logln("matched type: " + ttype + " and token = " - + currentToken.sval); nextToken(); } else { throw new SyntaxException(st.lineno()); @@ -105,7 +94,6 @@ public class AliasFileParser { */ private void match(int ttype) throws IOException, SyntaxException { if (currentToken.ttype == ttype) { - logln("matched type: " + ttype + ", token = " + currentToken.sval); nextToken(); } else { throw new SyntaxException(st.lineno()); @@ -157,8 +145,6 @@ public class AliasFileParser { } while ((currentToken.ttype != StreamTokenizer.TT_EOF) && (currentToken.sval.compareTo(ALIAS) != 0)); - logln("adding map entry for " + name + " values = " + aliases); - map.put(name, aliases); } } diff --git a/jdk/src/jdk.jvmstat/share/classes/sun/jvmstat/perfdata/monitor/CountedTimerTaskUtils.java b/jdk/src/jdk.jvmstat/share/classes/sun/jvmstat/perfdata/monitor/CountedTimerTaskUtils.java index b9c6d0a8717..8d86f601a96 100644 --- a/jdk/src/jdk.jvmstat/share/classes/sun/jvmstat/perfdata/monitor/CountedTimerTaskUtils.java +++ b/jdk/src/jdk.jvmstat/share/classes/sun/jvmstat/perfdata/monitor/CountedTimerTaskUtils.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 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 @@ -35,7 +35,7 @@ import java.util.*; */ public class CountedTimerTaskUtils { - private static final boolean DEBUG = false; + // 8028357 removed old, inefficient debug logging /** * Reschedule a CountedTimeTask at a different interval. Probably not @@ -58,14 +58,6 @@ public class CountedTimerTaskUtils { long lastRun = oldTask.scheduledExecutionTime(); long expired = now - lastRun; - if (DEBUG) { - System.err.println("computing timer delay: " - + " oldInterval = " + oldInterval - + " newInterval = " + newInterval - + " samples = " + oldTask.executionCount() - + " expired = " + expired); - } - /* * check if original task ever ran - if not, then lastRun is * undefined and we simply set the delay to 0. @@ -76,12 +68,6 @@ public class CountedTimerTaskUtils { delay = remainder >= 0 ? remainder : 0; } - if (DEBUG) { - System.err.println("rescheduling sampler task: interval = " - + newInterval - + " delay = " + delay); - } - timer.schedule(newTask, delay, newInterval); } } diff --git a/jdk/src/jdk.jvmstat/share/classes/sun/jvmstat/perfdata/monitor/v1_0/PerfDataBuffer.java b/jdk/src/jdk.jvmstat/share/classes/sun/jvmstat/perfdata/monitor/v1_0/PerfDataBuffer.java index 567a2c5d705..c444cf60b90 100644 --- a/jdk/src/jdk.jvmstat/share/classes/sun/jvmstat/perfdata/monitor/v1_0/PerfDataBuffer.java +++ b/jdk/src/jdk.jvmstat/share/classes/sun/jvmstat/perfdata/monitor/v1_0/PerfDataBuffer.java @@ -44,7 +44,8 @@ import java.nio.*; */ public class PerfDataBuffer extends PerfDataBufferImpl { - private static final boolean DEBUG = false; + // 8028357 removed old, inefficient debug logging + private static final int syncWaitMs = Integer.getInteger("sun.jvmstat.perdata.syncWaitMs", 5000); private static final ArrayList EMPTY_LIST = new ArrayList(0); @@ -268,18 +269,13 @@ public class PerfDataBuffer extends PerfDataBufferImpl { * loop waiting for the ticks counter to be non zero. This is * an indication that the jvm is initialized. */ - log("synchWithTarget: " + lvmid + " "); while (ticks.longValue() == 0) { - log("."); - try { Thread.sleep(20); } catch (InterruptedException e) { } if (System.currentTimeMillis() > timeLimit) { - lognl("failed: " + lvmid); throw new MonitorException("Could Not Synchronize with target"); } } - lognl("success: " + lvmid); } /** @@ -291,24 +287,18 @@ public class PerfDataBuffer extends PerfDataBufferImpl { throws MonitorException { Monitor monitor = null; - log("polling for: " + lvmid + "," + name + " "); - pollForEntry = nextEntry; while ((monitor = map.get(name)) == null) { - log("."); try { Thread.sleep(20); } catch (InterruptedException e) { } long t = System.currentTimeMillis(); if ((t > timeLimit) || (overflow.intValue() > 0)) { - lognl("failed: " + lvmid + "," + name); - dumpAll(map, lvmid); throw new MonitorException("Could not find expected counter"); } getNewMonitors(map); } - lognl("success: " + lvmid + "," + name); return monitor; } @@ -481,8 +471,6 @@ public class PerfDataBuffer extends PerfDataBufferImpl { // check for the end of the buffer if (nextEntry == buffer.limit()) { - lognl("getNextMonitorEntry():" - + " nextEntry == buffer.limit(): returning"); return null; } @@ -614,37 +602,4 @@ public class PerfDataBuffer extends PerfDataBufferImpl { nextEntry = entryStart + entryLength; return monitor; } - - /** - * Method to dump debugging information - */ - private void dumpAll(Map map, int lvmid) { - if (DEBUG) { - Set keys = map.keySet(); - - System.err.println("Dump for " + lvmid); - int j = 0; - for (Iterator i = keys.iterator(); i.hasNext(); j++) { - Monitor monitor = map.get(i.next()); - System.err.println(j + "\t" + monitor.getName() - + "=" + monitor.getValue()); - } - System.err.println("nextEntry = " + nextEntry - + " pollForEntry = " + pollForEntry); - System.err.println("Buffer info:"); - System.err.println("buffer = " + buffer); - } - } - - private void lognl(String s) { - if (DEBUG) { - System.err.println(s); - } - } - - private void log(String s) { - if (DEBUG) { - System.err.print(s); - } - } } diff --git a/jdk/src/jdk.jvmstat/share/classes/sun/jvmstat/perfdata/monitor/v2_0/PerfDataBuffer.java b/jdk/src/jdk.jvmstat/share/classes/sun/jvmstat/perfdata/monitor/v2_0/PerfDataBuffer.java index 2c2a944e0d7..f20a6f956dd 100644 --- a/jdk/src/jdk.jvmstat/share/classes/sun/jvmstat/perfdata/monitor/v2_0/PerfDataBuffer.java +++ b/jdk/src/jdk.jvmstat/share/classes/sun/jvmstat/perfdata/monitor/v2_0/PerfDataBuffer.java @@ -62,7 +62,8 @@ import java.nio.*; */ public class PerfDataBuffer extends PerfDataBufferImpl { - private static final boolean DEBUG = false; + // 8028357 removed old, inefficient debug logging + private static final int syncWaitMs = Integer.getInteger("sun.jvmstat.perdata.syncWaitMs", 5000); private static final ArrayList EMPTY_LIST = new ArrayList<>(0); @@ -264,20 +265,15 @@ public class PerfDataBuffer extends PerfDataBufferImpl { long timeLimit = System.currentTimeMillis() + syncWaitMs; // loop waiting for the accessible indicater to be non-zero - log("synchWithTarget: " + lvmid + " "); while (!prologue.isAccessible()) { - log("."); - // give the target jvm a chance to complete initializatoin try { Thread.sleep(20); } catch (InterruptedException e) { } if (System.currentTimeMillis() > timeLimit) { - logln("failed: " + lvmid); throw new MonitorException("Could not synchronize with target"); } } - logln("success: " + lvmid); } /** @@ -306,8 +302,6 @@ public class PerfDataBuffer extends PerfDataBufferImpl { // check for end of the buffer if (nextEntry == buffer.limit()) { - logln("getNextMonitorEntry():" - + " nextEntry == buffer.limit(): returning"); return null; } @@ -346,9 +340,6 @@ public class PerfDataBuffer extends PerfDataBufferImpl { byte varByte = buffer.get(); int dataOffset = buffer.getInt(); - dump_entry_fixed(entryStart, nameOffset, vectorLength, typeCodeByte, - flags, unitsByte, varByte, dataOffset); - // convert common attributes to their object types Units units = Units.toUnits(unitsByte); Variability variability = Variability.toVariability(varByte); @@ -439,8 +430,6 @@ public class PerfDataBuffer extends PerfDataBufferImpl { // set the position to the start of the data item buffer.position(entryStart + dataOffset); - dump_entry_variable(name, buffer, dataSize); - if (vectorLength == 0) { // create a scalar Monitor object if (typeCode == TypeCode.LONG) { @@ -514,103 +503,4 @@ public class PerfDataBuffer extends PerfDataBufferImpl { nextEntry = entryStart + entryLength; return monitor; } - - /** - * Method to dump debugging information - */ - private void dumpAll(Map map, int lvmid) { - if (DEBUG) { - Set keys = map.keySet(); - - System.err.println("Dump for " + lvmid); - int j = 0; - for (Iterator i = keys.iterator(); i.hasNext(); j++) { - Monitor monitor = map.get(i.next()); - System.err.println(j + "\t" + monitor.getName() - + "=" + monitor.getValue()); - } - System.err.println("nextEntry = " + nextEntry); - System.err.println("Buffer info:"); - System.err.println("buffer = " + buffer); - } - } - - /** - * Method to dump the fixed portion of an entry. - */ - private void dump_entry_fixed(int entry_start, int nameOffset, - int vectorLength, byte typeCodeByte, - byte flags, byte unitsByte, byte varByte, - int dataOffset) { - if (DEBUG) { - System.err.println("Entry at offset: 0x" - + Integer.toHexString(entry_start)); - System.err.println("\tname_offset = 0x" - + Integer.toHexString(nameOffset)); - System.err.println("\tvector_length = 0x" - + Integer.toHexString(vectorLength)); - System.err.println("\tdata_type = 0x" - + Integer.toHexString(typeCodeByte)); - System.err.println("\tflags = 0x" - + Integer.toHexString(flags)); - System.err.println("\tdata_units = 0x" - + Integer.toHexString(unitsByte)); - System.err.println("\tdata_variability = 0x" - + Integer.toHexString(varByte)); - System.err.println("\tdata_offset = 0x" - + Integer.toHexString(dataOffset)); - } - } - - private void dump_entry_variable(String name, ByteBuffer bb, int size) { - if (DEBUG) { - char[] toHex = new char[] { '0', '1', '2', '3', - '4', '5', '6', '7', - '8', '9', 'a', 'b', - 'c', 'd', 'e', 'f' }; - - ByteBuffer data = bb.slice(); - data.limit(size); - - System.err.println("\tname = " + name); - System.err.println("\tdata = "); - - int count=0; - while (data.hasRemaining()) { - byte b = data.get(); - byte high = (byte)((b >> 8) & 0x0f); - byte low = (byte)(b & 0x0f); - - if (count % 16 == 0) { - System.err.print("\t\t" + Integer.toHexString(count / 16) - + ": "); - } - - System.err.print(String.valueOf(toHex[high]) - + String.valueOf(toHex[low])); - - count++; - if (count % 16 == 0) { - System.err.println(); - } else { - System.err.print(" "); - } - } - if (count % 16 != 0) { - System.err.println(); - } - } - } - - private void logln(String s) { - if (DEBUG) { - System.err.println(s); - } - } - - private void log(String s) { - if (DEBUG) { - System.err.print(s); - } - } } diff --git a/jdk/test/ProblemList.txt b/jdk/test/ProblemList.txt index aaf704fa77b..58025926ace 100644 --- a/jdk/test/ProblemList.txt +++ b/jdk/test/ProblemList.txt @@ -120,6 +120,10 @@ # jdk_lang +# 8029891 +java/lang/ClassLoader/deadlock/GetResource.java generic-all + + ############################################################################ # jdk_instrument @@ -261,7 +265,7 @@ java/security/Security/ClassLoaderDeadlock/Deadlock2.sh generic-all # Tests take too long, on sparcs see 7143279 # also see 8059906 -tools/pack200/CommandLineTests.java +tools/pack200/CommandLineTests.java generic-all tools/pack200/Pack200Test.java solaris-all,macosx-all # 8007410 diff --git a/jdk/test/com/sun/corba/5036554/TestCorbaBug.sh b/jdk/test/com/sun/corba/5036554/TestCorbaBug.sh index 4f0ff231a99..e8b4365b68f 100644 --- a/jdk/test/com/sun/corba/5036554/TestCorbaBug.sh +++ b/jdk/test/com/sun/corba/5036554/TestCorbaBug.sh @@ -75,13 +75,13 @@ ${TESTJAVA}${FS}bin${FS}java -version mkdir bug cp ${TESTSRC}${FS}bug.idl . -${TESTJAVA}${FS}bin${FS}idlj bug.idl +${COMPILEJAVA}${FS}bin${FS}idlj bug.idl cp ${TESTSRC}${FS}JavaBug.java bug chmod -fR 777 bug -${TESTJAVA}${FS}bin${FS}javac -d . bug${FS}*.java +${COMPILEJAVA}${FS}bin${FS}javac -d . bug${FS}*.java ${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} -cp . bug/JavaBug > test.out 2>&1 diff --git a/jdk/test/com/sun/corba/cachedSocket/7056731.sh b/jdk/test/com/sun/corba/cachedSocket/7056731.sh index 3db0f73660f..2e5e3fb8547 100644 --- a/jdk/test/com/sun/corba/cachedSocket/7056731.sh +++ b/jdk/test/com/sun/corba/cachedSocket/7056731.sh @@ -55,8 +55,8 @@ PORT=1052 cp -r ${TESTSRC}${FS}*.java ${TESTSRC}${FS}Hello.idl . echo "Testing...please wait" -${TESTJAVA}${FS}bin${FS}idlj -fall Hello.idl -${TESTJAVA}${FS}bin${FS}javac *.java HelloApp/*.java +${COMPILEJAVA}${FS}bin${FS}idlj -fall Hello.idl +${COMPILEJAVA}${FS}bin${FS}javac *.java HelloApp/*.java echo "starting orbd" ${TESTJAVA}${FS}bin${FS}orbd -ORBInitialPort $PORT -ORBInitialHost localhost & diff --git a/jdk/test/com/sun/crypto/provider/Cipher/DES/TestUtility.java b/jdk/test/com/sun/crypto/provider/Cipher/DES/TestUtility.java index 61efd621bdb..ffa0a5bfcb3 100644 --- a/jdk/test/com/sun/crypto/provider/Cipher/DES/TestUtility.java +++ b/jdk/test/com/sun/crypto/provider/Cipher/DES/TestUtility.java @@ -27,39 +27,52 @@ public class TestUtility { - private static final String digits = "0123456789abcdef"; + private static final String DIGITS = "0123456789abcdef"; - public TestUtility() { + private TestUtility() { } public static String hexDump(byte[] bytes) { - StringBuffer buf = new StringBuffer (bytes.length * 2); - int i; + StringBuilder buf = new StringBuilder(bytes.length * 2); + int i; - buf.append (" "); // four spaces + buf.append(" "); // four spaces for (i = 0; i < bytes.length; i++) { - buf.append (digits.charAt ((bytes[i] >> 4) & 0x0f)); - buf.append (digits.charAt (bytes[i] & 0x0f)); - if (((i + 1) % 32) == 0) { - if ((i + 1) != bytes.length) - buf.append ("\n "); // line after four words - } else if (((i + 1) % 4) == 0) - buf.append (' '); // space between words + buf.append(DIGITS.charAt(bytes[i] >> 4 & 0x0f)); + buf.append(DIGITS.charAt(bytes[i] & 0x0f)); + if ((i + 1) % 32 == 0) { + if (i + 1 != bytes.length) { + buf.append("\n "); // line after four words + } + } else if ((i + 1) % 4 == 0) { + buf.append(' '); // space between words + } } - return buf.toString (); + return buf.toString(); } + public static String hexDump(byte[] bytes, int index) { + StringBuilder buf = new StringBuilder(bytes.length * 2); + int i; + + buf.append(" "); // four spaces + buf.append(DIGITS.charAt(bytes[index] >> 4 & 0x0f)); + buf.append(DIGITS.charAt(bytes[index] & 0x0f)); + return buf.toString(); + } public static boolean equalsBlock(byte[] b1, byte[] b2) { - if (b1.length != b2.length) + if (b1.length != b2.length) { return false; + } - for (int i=0; i 0) throw new RuntimeException(failed + " test(s) failed - see log for details"); diff --git a/jdk/test/java/nio/channels/FileChannel/TransferToChannel.java b/jdk/test/java/nio/channels/FileChannel/TransferToChannel.java index 2aa1b4bd2cc..44e96337b27 100644 --- a/jdk/test/java/nio/channels/FileChannel/TransferToChannel.java +++ b/jdk/test/java/nio/channels/FileChannel/TransferToChannel.java @@ -25,7 +25,7 @@ * @bug 4652496 * @summary Test transferTo with different target channels * @run main TransferToChannel - * @run main/othervm -Djdk.net.enableFastFileTransfer TransferToChannel + * @run main/othervm -Djdk.nio.enableFastFileTransfer TransferToChannel */ import java.nio.channels.FileChannel; diff --git a/jdk/test/java/rmi/activation/Activatable/checkActivateRef/group.security.policy b/jdk/test/java/rmi/activation/Activatable/checkActivateRef/group.security.policy index 2130c464a88..02604b7eeb3 100644 --- a/jdk/test/java/rmi/activation/Activatable/checkActivateRef/group.security.policy +++ b/jdk/test/java/rmi/activation/Activatable/checkActivateRef/group.security.policy @@ -4,8 +4,8 @@ grant { permission java.io.FilePermission "..${/}..${/}test.props", "read"; - - // test needs to communicate with the activation system permission java.net.SocketPermission "*:1024-", "connect,accept,listen"; + permission java.util.PropertyPermission "test.*", "read"; + permission java.lang.RuntimePermission "getClassLoader"; }; diff --git a/jdk/test/java/rmi/activation/Activatable/checkAnnotations/group.security.policy b/jdk/test/java/rmi/activation/Activatable/checkAnnotations/group.security.policy index a6115faf6df..276768a15d1 100644 --- a/jdk/test/java/rmi/activation/Activatable/checkAnnotations/group.security.policy +++ b/jdk/test/java/rmi/activation/Activatable/checkAnnotations/group.security.policy @@ -1,10 +1,9 @@ /* - * security policy used by activation groups. + * security policy used by activation groups */ grant { permission java.io.FilePermission "..${/}..${/}test.props", "read"; - - // test needs to communicate with the activation system permission java.net.SocketPermission "*:1024-", "connect,accept,listen"; + permission java.util.PropertyPermission "test.*", "read"; }; diff --git a/jdk/test/java/rmi/activation/Activatable/checkRegisterInLog/group.security.policy b/jdk/test/java/rmi/activation/Activatable/checkRegisterInLog/group.security.policy index 6c8dc8a0d06..276768a15d1 100644 --- a/jdk/test/java/rmi/activation/Activatable/checkRegisterInLog/group.security.policy +++ b/jdk/test/java/rmi/activation/Activatable/checkRegisterInLog/group.security.policy @@ -4,10 +4,6 @@ grant { permission java.io.FilePermission "..${/}..${/}test.props", "read"; - - // allow remote objects to be exported on arbitrary ports. - permission java.net.SocketPermission "*:1024-", "connect,accept"; - - // allow exporting object with non-public remote interface - permission java.rmi.RMIPermission "exportRemoteInterface.ActivateMe"; + permission java.net.SocketPermission "*:1024-", "connect,accept,listen"; + permission java.util.PropertyPermission "test.*", "read"; }; diff --git a/jdk/test/java/rmi/activation/Activatable/createPrivateActivable/group.security.policy b/jdk/test/java/rmi/activation/Activatable/createPrivateActivable/group.security.policy index e7a403e569a..276768a15d1 100644 --- a/jdk/test/java/rmi/activation/Activatable/createPrivateActivable/group.security.policy +++ b/jdk/test/java/rmi/activation/Activatable/createPrivateActivable/group.security.policy @@ -1,13 +1,9 @@ /* - * security policy used activation groups + * security policy used by activation groups */ grant { permission java.io.FilePermission "..${/}..${/}test.props", "read"; - - // test needs to communicate with the activation system permission java.net.SocketPermission "*:1024-", "connect,accept,listen"; - - // allow exporting object with non-public remote interface - permission java.rmi.RMIPermission "exportRemoteInterface.ActivateMe"; + permission java.util.PropertyPermission "test.*", "read"; }; diff --git a/jdk/test/java/rmi/activation/Activatable/downloadParameterClass/group.security.policy b/jdk/test/java/rmi/activation/Activatable/downloadParameterClass/group.security.policy index 38258b4b45c..41abd5dd468 100644 --- a/jdk/test/java/rmi/activation/Activatable/downloadParameterClass/group.security.policy +++ b/jdk/test/java/rmi/activation/Activatable/downloadParameterClass/group.security.policy @@ -1,14 +1,15 @@ /* - * security policy used exec'ed activation groups + * security policy used by activation groups */ grant { + permission java.io.FilePermission "..${/}..${/}test.props", "read"; + permission java.net.SocketPermission "*:1024-", "connect,accept,listen"; + permission java.util.PropertyPermission "test.*", "read"; + // need to load custom security manager and activation group from a new codebase permission java.io.FilePermission ".${/}codebase1", "read,write,delete"; permission java.io.FilePermission ".${/}codebase1${/}-", "read,write"; permission java.io.FilePermission ".${/}codebase2", "read,write,delete"; permission java.io.FilePermission ".${/}codebase2${/}-", "read,write,delete"; - - // allow remote objects to be exported on arbitrary ports. - permission java.net.SocketPermission "*:1024-", "connect,accept,listen"; }; diff --git a/jdk/test/java/rmi/activation/Activatable/elucidateNoSuchMethod/group.security.policy b/jdk/test/java/rmi/activation/Activatable/elucidateNoSuchMethod/group.security.policy index 3cc19105e0f..bf7d8c414b9 100644 --- a/jdk/test/java/rmi/activation/Activatable/elucidateNoSuchMethod/group.security.policy +++ b/jdk/test/java/rmi/activation/Activatable/elucidateNoSuchMethod/group.security.policy @@ -1,12 +1,13 @@ /* - * security policy used activation groups + * security policy used by activation groups */ grant { + permission java.io.FilePermission "..${/}..${/}test.props", "read"; + permission java.net.SocketPermission "*:1024-", "connect,accept,listen"; + permission java.util.PropertyPermission "test.*", "read"; + // Needed because of bug#: 4182104 permission java.lang.RuntimePermission "modifyThreadGroup"; permission java.lang.RuntimePermission "modifyThread"; - - // allow remote objects to be exported on arbitrary ports. - permission java.net.SocketPermission "*:1024-", "connect,accept,listen"; }; diff --git a/jdk/test/java/rmi/activation/Activatable/extLoadedImpl/group.security.policy b/jdk/test/java/rmi/activation/Activatable/extLoadedImpl/group.security.policy index 09e121a74f9..276768a15d1 100644 --- a/jdk/test/java/rmi/activation/Activatable/extLoadedImpl/group.security.policy +++ b/jdk/test/java/rmi/activation/Activatable/extLoadedImpl/group.security.policy @@ -1,8 +1,9 @@ /* - * security policy used exec'ed activation groups + * security policy used by activation groups */ grant { - // allow remote objects to be exported on arbitrary ports. + permission java.io.FilePermission "..${/}..${/}test.props", "read"; permission java.net.SocketPermission "*:1024-", "connect,accept,listen"; + permission java.util.PropertyPermission "test.*", "read"; }; diff --git a/jdk/test/java/rmi/activation/Activatable/forceLogSnapshot/group.security.policy b/jdk/test/java/rmi/activation/Activatable/forceLogSnapshot/group.security.policy index f5637355114..276768a15d1 100644 --- a/jdk/test/java/rmi/activation/Activatable/forceLogSnapshot/group.security.policy +++ b/jdk/test/java/rmi/activation/Activatable/forceLogSnapshot/group.security.policy @@ -3,9 +3,7 @@ */ grant { - // allow remote objects to be exported on arbitrary ports. + permission java.io.FilePermission "..${/}..${/}test.props", "read"; permission java.net.SocketPermission "*:1024-", "connect,accept,listen"; - - // allow exporting object with non-public remote interface - permission java.rmi.RMIPermission "exportRemoteInterface.ActivateMe"; + permission java.util.PropertyPermission "test.*", "read"; }; diff --git a/jdk/test/java/rmi/activation/Activatable/inactiveGroup/group.security.policy b/jdk/test/java/rmi/activation/Activatable/inactiveGroup/group.security.policy index f1d7ad2f1a0..276768a15d1 100644 --- a/jdk/test/java/rmi/activation/Activatable/inactiveGroup/group.security.policy +++ b/jdk/test/java/rmi/activation/Activatable/inactiveGroup/group.security.policy @@ -4,10 +4,6 @@ grant { permission java.io.FilePermission "..${/}..${/}test.props", "read"; - - // allow remote objects to be exported on arbitrary ports. permission java.net.SocketPermission "*:1024-", "connect,accept,listen"; - - // allow exporting object with non-public remote interface - permission java.rmi.RMIPermission "exportRemoteInterface.ActivateMe"; + permission java.util.PropertyPermission "test.*", "read"; }; diff --git a/jdk/test/java/rmi/activation/Activatable/nestedActivate/group.security.policy b/jdk/test/java/rmi/activation/Activatable/nestedActivate/group.security.policy index cbb1d41bfe4..276768a15d1 100644 --- a/jdk/test/java/rmi/activation/Activatable/nestedActivate/group.security.policy +++ b/jdk/test/java/rmi/activation/Activatable/nestedActivate/group.security.policy @@ -1,13 +1,9 @@ /* - * security policy used by test activation groups + * security policy used by activation groups */ grant { permission java.io.FilePermission "..${/}..${/}test.props", "read"; - - // allow remote objects to be exported on arbitrary ports. permission java.net.SocketPermission "*:1024-", "connect,accept,listen"; - - // allow exporting of non-public remote interface - permission java.rmi.RMIPermission "exportRemoteInterface.ActivateMe"; + permission java.util.PropertyPermission "test.*", "read"; }; diff --git a/jdk/test/java/rmi/activation/Activatable/nonExistentActivatable/group.security.policy b/jdk/test/java/rmi/activation/Activatable/nonExistentActivatable/group.security.policy index a830e95dfe0..276768a15d1 100644 --- a/jdk/test/java/rmi/activation/Activatable/nonExistentActivatable/group.security.policy +++ b/jdk/test/java/rmi/activation/Activatable/nonExistentActivatable/group.security.policy @@ -4,7 +4,6 @@ grant { permission java.io.FilePermission "..${/}..${/}test.props", "read"; - - // allow remote objects to be exported on arbitrary ports. permission java.net.SocketPermission "*:1024-", "connect,accept,listen"; + permission java.util.PropertyPermission "test.*", "read"; }; diff --git a/jdk/test/java/rmi/activation/Activatable/restartCrashedService/group.security.policy b/jdk/test/java/rmi/activation/Activatable/restartCrashedService/group.security.policy index ce2fdaf45df..276768a15d1 100644 --- a/jdk/test/java/rmi/activation/Activatable/restartCrashedService/group.security.policy +++ b/jdk/test/java/rmi/activation/Activatable/restartCrashedService/group.security.policy @@ -1,8 +1,9 @@ /* - * security policy used by test activation groups + * security policy used by activation groups */ grant { - // test needs to communicate with the activation system + permission java.io.FilePermission "..${/}..${/}test.props", "read"; permission java.net.SocketPermission "*:1024-", "connect,accept,listen"; + permission java.util.PropertyPermission "test.*", "read"; }; diff --git a/jdk/test/java/rmi/activation/Activatable/restartLatecomer/group.security.policy b/jdk/test/java/rmi/activation/Activatable/restartLatecomer/group.security.policy index 67f3c249496..276768a15d1 100644 --- a/jdk/test/java/rmi/activation/Activatable/restartLatecomer/group.security.policy +++ b/jdk/test/java/rmi/activation/Activatable/restartLatecomer/group.security.policy @@ -3,6 +3,7 @@ */ grant { - // allow remote objects to be exported on arbitrary ports. + permission java.io.FilePermission "..${/}..${/}test.props", "read"; permission java.net.SocketPermission "*:1024-", "connect,accept,listen"; + permission java.util.PropertyPermission "test.*", "read"; }; diff --git a/jdk/test/java/rmi/activation/Activatable/restartService/group.security.policy b/jdk/test/java/rmi/activation/Activatable/restartService/group.security.policy index 67f3c249496..276768a15d1 100644 --- a/jdk/test/java/rmi/activation/Activatable/restartService/group.security.policy +++ b/jdk/test/java/rmi/activation/Activatable/restartService/group.security.policy @@ -3,6 +3,7 @@ */ grant { - // allow remote objects to be exported on arbitrary ports. + permission java.io.FilePermission "..${/}..${/}test.props", "read"; permission java.net.SocketPermission "*:1024-", "connect,accept,listen"; + permission java.util.PropertyPermission "test.*", "read"; }; diff --git a/jdk/test/java/rmi/activation/Activatable/shutdownGracefully/group.security.policy b/jdk/test/java/rmi/activation/Activatable/shutdownGracefully/group.security.policy index e1a3f30b029..276768a15d1 100644 --- a/jdk/test/java/rmi/activation/Activatable/shutdownGracefully/group.security.policy +++ b/jdk/test/java/rmi/activation/Activatable/shutdownGracefully/group.security.policy @@ -1,10 +1,9 @@ /* - * security policy used activation groups + * security policy used by activation groups */ grant { permission java.io.FilePermission "..${/}..${/}test.props", "read"; - - // test needs to communicate with the activation system permission java.net.SocketPermission "*:1024-", "connect,accept,listen"; + permission java.util.PropertyPermission "test.*", "read"; }; diff --git a/jdk/test/java/rmi/activation/Activatable/unregisterInactive/group.security.policy b/jdk/test/java/rmi/activation/Activatable/unregisterInactive/group.security.policy index a830e95dfe0..276768a15d1 100644 --- a/jdk/test/java/rmi/activation/Activatable/unregisterInactive/group.security.policy +++ b/jdk/test/java/rmi/activation/Activatable/unregisterInactive/group.security.policy @@ -4,7 +4,6 @@ grant { permission java.io.FilePermission "..${/}..${/}test.props", "read"; - - // allow remote objects to be exported on arbitrary ports. permission java.net.SocketPermission "*:1024-", "connect,accept,listen"; + permission java.util.PropertyPermission "test.*", "read"; }; diff --git a/jdk/test/java/rmi/activation/ActivateFailedException/activateFails/group.security.policy b/jdk/test/java/rmi/activation/ActivateFailedException/activateFails/group.security.policy index 543fc1d345e..276768a15d1 100644 --- a/jdk/test/java/rmi/activation/ActivateFailedException/activateFails/group.security.policy +++ b/jdk/test/java/rmi/activation/ActivateFailedException/activateFails/group.security.policy @@ -1,8 +1,9 @@ /* - * security policy used activation groups + * security policy used by activation groups */ grant { - // test needs to communicate with the activation system + permission java.io.FilePermission "..${/}..${/}test.props", "read"; permission java.net.SocketPermission "*:1024-", "connect,accept,listen"; + permission java.util.PropertyPermission "test.*", "read"; }; diff --git a/jdk/test/java/rmi/activation/ActivationGroup/downloadActivationGroup/group.security.policy b/jdk/test/java/rmi/activation/ActivationGroup/downloadActivationGroup/group.security.policy index d4b2d5ded47..b290738202a 100644 --- a/jdk/test/java/rmi/activation/ActivationGroup/downloadActivationGroup/group.security.policy +++ b/jdk/test/java/rmi/activation/ActivationGroup/downloadActivationGroup/group.security.policy @@ -1,10 +1,11 @@ /* - * security policy used by downloaded activation group + * security policy used by activation groups */ grant { permission java.io.FilePermission "..${/}..${/}test.props", "read"; + permission java.net.SocketPermission "*:1024-", "connect,accept,listen"; + permission java.util.PropertyPermission "test.*", "read"; permission java.lang.RuntimePermission "accessClassInPackage.sun.rmi.server"; - permission java.net.SocketPermission "*:1024-", "connect,accept,listen"; }; diff --git a/jdk/test/java/rmi/activation/ActivationSystem/modifyDescriptor/group.security.policy b/jdk/test/java/rmi/activation/ActivationSystem/modifyDescriptor/group.security.policy index 9f404883c86..276768a15d1 100644 --- a/jdk/test/java/rmi/activation/ActivationSystem/modifyDescriptor/group.security.policy +++ b/jdk/test/java/rmi/activation/ActivationSystem/modifyDescriptor/group.security.policy @@ -4,10 +4,6 @@ grant { permission java.io.FilePermission "..${/}..${/}test.props", "read"; - - // accomodate property used by this test. - permission java.util.PropertyPermission "test.message", "read"; - - // test needs to communicate with the activation system permission java.net.SocketPermission "*:1024-", "connect,accept,listen"; + permission java.util.PropertyPermission "test.*", "read"; }; diff --git a/jdk/test/java/rmi/activation/ActivationSystem/stubClassesPermitted/group.security.policy b/jdk/test/java/rmi/activation/ActivationSystem/stubClassesPermitted/group.security.policy index 7876a38e1fb..c99d2e288a2 100644 --- a/jdk/test/java/rmi/activation/ActivationSystem/stubClassesPermitted/group.security.policy +++ b/jdk/test/java/rmi/activation/ActivationSystem/stubClassesPermitted/group.security.policy @@ -1,13 +1,11 @@ /* - * security policy used by activation groups. + * security policy used by activation groups */ grant { permission java.io.FilePermission "..${/}..${/}test.props", "read"; - - // give the group permission to create a class that the main test process can not create - permission java.lang.RuntimePermission "accessClassInPackage.sun.security.provider"; - - // test needs to communicate with the activation system permission java.net.SocketPermission "*:1024-", "connect,accept,listen"; + permission java.util.PropertyPermission "test.*", "read"; + + permission java.lang.RuntimePermission "accessClassInPackage.sun.security.provider"; }; diff --git a/jdk/test/java/rmi/activation/ActivationSystem/unregisterGroup/group.security.policy b/jdk/test/java/rmi/activation/ActivationSystem/unregisterGroup/group.security.policy index e596baae478..276768a15d1 100644 --- a/jdk/test/java/rmi/activation/ActivationSystem/unregisterGroup/group.security.policy +++ b/jdk/test/java/rmi/activation/ActivationSystem/unregisterGroup/group.security.policy @@ -4,8 +4,6 @@ grant { permission java.io.FilePermission "..${/}..${/}test.props", "read"; - - // test needs to communicate with the activation system permission java.net.SocketPermission "*:1024-", "connect,accept,listen"; - permission java.util.PropertyPermission "unregisterGroup.port", "read"; + permission java.util.PropertyPermission "test.*", "read"; }; diff --git a/jdk/test/java/rmi/activation/CommandEnvironment/group.security.policy b/jdk/test/java/rmi/activation/CommandEnvironment/group.security.policy index 479f351a1e5..276768a15d1 100644 --- a/jdk/test/java/rmi/activation/CommandEnvironment/group.security.policy +++ b/jdk/test/java/rmi/activation/CommandEnvironment/group.security.policy @@ -1,8 +1,9 @@ /* - * security policy used by activation groups. + * security policy used by activation groups */ grant { - // test needs to communicate with the activation system + permission java.io.FilePermission "..${/}..${/}test.props", "read"; permission java.net.SocketPermission "*:1024-", "connect,accept,listen"; + permission java.util.PropertyPermission "test.*", "read"; }; diff --git a/jdk/test/java/rmi/server/RMISocketFactory/useSocketFactory/activatable/group.security.policy b/jdk/test/java/rmi/server/RMISocketFactory/useSocketFactory/activatable/group.security.policy index 810baf41d4b..276768a15d1 100644 --- a/jdk/test/java/rmi/server/RMISocketFactory/useSocketFactory/activatable/group.security.policy +++ b/jdk/test/java/rmi/server/RMISocketFactory/useSocketFactory/activatable/group.security.policy @@ -1,11 +1,9 @@ /* - * security policy used by the rmid process exec'ed by a running - * instance of the test. + * security policy used by activation groups */ grant { permission java.io.FilePermission "..${/}..${/}test.props", "read"; - - // test needs to communicate with the activation system permission java.net.SocketPermission "*:1024-", "connect,accept,listen"; + permission java.util.PropertyPermission "test.*", "read"; }; diff --git a/jdk/test/java/rmi/server/RemoteServer/setLogPermission/SetLogPermission.java b/jdk/test/java/rmi/server/RemoteServer/setLogPermission/SetLogPermission.java index 2353dab0b4b..fd6c6ad5b62 100644 --- a/jdk/test/java/rmi/server/RemoteServer/setLogPermission/SetLogPermission.java +++ b/jdk/test/java/rmi/server/RemoteServer/setLogPermission/SetLogPermission.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2015, 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 @@ -27,7 +27,7 @@ * The RemoteServer.setLog method requires * java.util.log.LoggingPermission("control"). * @author Ann Wollrath - * @run main/othervm/policy=java.policy SetLogPermission + * @run main/othervm/policy=security.policy SetLogPermission */ import java.rmi.server.RemoteServer; diff --git a/jdk/test/java/rmi/server/RemoteServer/setLogPermission/java.policy b/jdk/test/java/rmi/server/RemoteServer/setLogPermission/security.policy similarity index 100% rename from jdk/test/java/rmi/server/RemoteServer/setLogPermission/java.policy rename to jdk/test/java/rmi/server/RemoteServer/setLogPermission/security.policy diff --git a/jdk/test/java/rmi/testlibrary/ActivationLibrary.java b/jdk/test/java/rmi/testlibrary/ActivationLibrary.java index 6a7a5b753d8..75531a97017 100644 --- a/jdk/test/java/rmi/testlibrary/ActivationLibrary.java +++ b/jdk/test/java/rmi/testlibrary/ActivationLibrary.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2015, 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 @@ -40,20 +40,6 @@ import java.rmi.registry.LocateRegistry; * objects. */ public class ActivationLibrary { - /** time safeDestroy should wait before failing on shutdown rmid */ - private static final int SAFE_WAIT_TIME; - static { - int slopFactor = 1; - try { - slopFactor = Integer.valueOf( - TestLibrary.getExtraProperty("jcov.sleep.multiplier","1")); - } catch (NumberFormatException ignore) {} - SAFE_WAIT_TIME = 60000 * slopFactor; - } - - private static final String SYSTEM_NAME = - ActivationSystem.class.getName(); - private static void mesg(Object mesg) { System.err.println("ACTIVATION_LIBRARY: " + mesg.toString()); } @@ -63,20 +49,19 @@ public class ActivationLibrary { */ public static void deactivate(Remote remote, ActivationID id) { - // We do as much as 50 deactivation trials, each separated by - // at least 100 milliseconds sleep time (max sleep time of 5 secs). - final long deactivateSleepTime = 100; - long stopTime = System.currentTimeMillis() + deactivateSleepTime * 50; - while (System.currentTimeMillis() < stopTime) { + final long POLLTIME_MS = 100L; + final long DEACTIVATE_TIME_MS = 30_000L; + + long startTime = System.currentTimeMillis(); + long deadline = TestLibrary.computeDeadline(startTime, DEACTIVATE_TIME_MS); + + while (System.currentTimeMillis() < deadline) { try { if (Activatable.inactive(id) == true) { mesg("inactive successful"); return; } else { - mesg("inactive trial failed. Sleeping " + - deactivateSleepTime + - " milliseconds before next trial"); - Thread.sleep(deactivateSleepTime); + Thread.sleep(POLLTIME_MS); } } catch (InterruptedException e) { Thread.currentThread().interrupt(); @@ -95,7 +80,8 @@ public class ActivationLibrary { } } - mesg("unable to inactivate after several attempts"); + mesg("unable to inactivate after " + + (System.currentTimeMillis() - startTime) + "ms."); mesg("unexporting object forcibly instead"); try { diff --git a/jdk/test/java/rmi/testlibrary/JavaVM.java b/jdk/test/java/rmi/testlibrary/JavaVM.java index b304cd25213..b0c4afd1113 100644 --- a/jdk/test/java/rmi/testlibrary/JavaVM.java +++ b/jdk/test/java/rmi/testlibrary/JavaVM.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2015, 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 @@ -194,7 +194,7 @@ public class JavaVM { throws InterruptedException, TimeoutException { if (vm == null) throw new IllegalStateException("can't wait for JavaVM that isn't running"); - long deadline = computeDeadline(System.currentTimeMillis(), timeout); + long deadline = TestLibrary.computeDeadline(System.currentTimeMillis(), timeout); while (true) { try { @@ -218,21 +218,4 @@ public class JavaVM { start(); return waitFor(); } - - /** - * Computes a deadline from a timestamp and a timeout value. - * Maximum timeout (before multipliers are applied) is one hour. - */ - public static long computeDeadline(long timestamp, long timeout) { - final long MAX_TIMEOUT_MS = 3_600_000L; - - if (timeout < 0L || timeout > MAX_TIMEOUT_MS) { - throw new IllegalArgumentException("timeout " + timeout + "ms out of range"); - } - - // TODO apply test.timeout.factor (and possibly jcov.sleep.multiplier) - // here instead of upstream - - return timestamp + timeout; - } } diff --git a/jdk/test/java/rmi/testlibrary/RMID.java b/jdk/test/java/rmi/testlibrary/RMID.java index 48fb49aa4d2..1ae6cf64bab 100644 --- a/jdk/test/java/rmi/testlibrary/RMID.java +++ b/jdk/test/java/rmi/testlibrary/RMID.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2015, 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 @@ -249,15 +249,15 @@ public class RMID extends JavaVM { mesg("Starting rmid on port " + port + "."); super.start(); - int slopFactor = 1; - try { - slopFactor = Integer.valueOf( - TestLibrary.getExtraProperty("jcov.sleep.multiplier","1")); - } catch (NumberFormatException ignore) {} - waitTime = waitTime * slopFactor; + // int slopFactor = 1; + // try { + // slopFactor = Integer.valueOf( + // TestLibrary.getExtraProperty("jcov.sleep.multiplier","1")); + // } catch (NumberFormatException ignore) {} + // waitTime = waitTime * slopFactor; long startTime = System.currentTimeMillis(); - long deadline = computeDeadline(startTime, waitTime); + long deadline = TestLibrary.computeDeadline(startTime, waitTime); while (true) { try { diff --git a/jdk/test/java/rmi/testlibrary/TestLibrary.java b/jdk/test/java/rmi/testlibrary/TestLibrary.java index 7165c678e6d..a8077ed8207 100644 --- a/jdk/test/java/rmi/testlibrary/TestLibrary.java +++ b/jdk/test/java/rmi/testlibrary/TestLibrary.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2015, 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 @@ -135,7 +135,8 @@ public class TestLibrary { */ public static boolean checkIfRegistryRunning(int port, int msTimeout) { - long stopTime = System.currentTimeMillis() + msTimeout; + final long POLLTIME_MS = 100L; + long stopTime = computeDeadline(System.currentTimeMillis(), msTimeout); do { try { Registry r = LocateRegistry.getRegistry(port); @@ -145,12 +146,12 @@ public class TestLibrary { } catch (RemoteException e) { // problem - not ready ? Try again try { - Thread.sleep(500); + Thread.sleep(POLLTIME_MS); } catch (InterruptedException ie) { // not expected } } - } while (stopTime > System.currentTimeMillis()); + } while (System.currentTimeMillis() < stopTime); return false; } @@ -169,6 +170,31 @@ public class TestLibrary { } } + public static double getTimeoutFactor() { + String prop = getProperty("test.timeout.factor", "1.0"); + double timeoutFactor = 1.0; + + try { + timeoutFactor = Double.parseDouble(prop); + } catch (NumberFormatException ignore) { } + + return timeoutFactor; + } + + /** + * Computes a deadline from a timestamp and a timeout value. + * Maximum timeout (before multipliers are applied) is one hour. + */ + public static long computeDeadline(long timestamp, long timeout) { + final long MAX_TIMEOUT_MS = 3_600_000L; + + if (timeout < 0L || timeout > MAX_TIMEOUT_MS) { + throw new IllegalArgumentException("timeout " + timeout + "ms out of range"); + } + + return timestamp + (long)(timeout * getTimeoutFactor()); + } + /** * Property mutators */ diff --git a/jdk/test/java/util/Formatter/Basic-X.java.template b/jdk/test/java/util/Formatter/Basic-X.java.template index 47c5516be49..57d77ae887d 100644 --- a/jdk/test/java/util/Formatter/Basic-X.java.template +++ b/jdk/test/java/util/Formatter/Basic-X.java.template @@ -1154,6 +1154,10 @@ public class Basic$Type$ extends Basic { test("%.5f", "0.99960", val); test("%.6f", "0.999600", val); + val = new BigDecimal(BigInteger.ZERO, 6); + test("%.4f", "0.0000", val); + val = new BigDecimal(BigInteger.ZERO, -6); + test("%.4f", "0.0000", val); #end[BigDecimal] #if[float] diff --git a/jdk/test/java/util/Formatter/Basic.java b/jdk/test/java/util/Formatter/Basic.java index 9624def5cea..31fce5dd4e2 100644 --- a/jdk/test/java/util/Formatter/Basic.java +++ b/jdk/test/java/util/Formatter/Basic.java @@ -26,6 +26,7 @@ * @bug 4906370 4962433 4973103 4989961 5005818 5031150 4970931 4989491 5002937 * 5005104 5007745 5061412 5055180 5066788 5088703 6317248 6318369 6320122 * 6344623 6369500 6534606 6282094 6286592 6476425 5063507 6469160 6476168 + * 8059175 * * @run shell/timeout=240 Basic.sh */ diff --git a/jdk/test/java/util/Formatter/BasicBigDecimal.java b/jdk/test/java/util/Formatter/BasicBigDecimal.java index 00a04f4535f..0eca6f987dd 100644 --- a/jdk/test/java/util/Formatter/BasicBigDecimal.java +++ b/jdk/test/java/util/Formatter/BasicBigDecimal.java @@ -1154,6 +1154,11 @@ public class BasicBigDecimal extends Basic { test("%.5f", "0.99960", val); test("%.6f", "0.999600", val); + val = new BigDecimal(BigInteger.ZERO, 6); + test("%.4f", "0.0000", val); + + val = new BigDecimal(BigInteger.ZERO, -6); + test("%.4f", "0.0000", val); diff --git a/jdk/test/javax/crypto/KeyGenerator/TestKGParity.java b/jdk/test/javax/crypto/KeyGenerator/TestKGParity.java new file mode 100644 index 00000000000..40752152c56 --- /dev/null +++ b/jdk/test/javax/crypto/KeyGenerator/TestKGParity.java @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2015, 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 java.io.PrintStream; +import java.lang.String; +import java.lang.System; +import java.security.Provider; +import java.security.SecureRandom; +import java.security.Security; +import javax.crypto.KeyGenerator; +import static java.lang.System.out; + +/* + * @test + * @bug 8048607 + * @compile ../../../com/sun/crypto/provider/Cipher/DES/TestUtility.java + * @summary Test key generation of DES and DESEDE + */ +public class TestKGParity { + + private static final String[] ALGORITHM_ARR = { + "deS", "DesEDE" + }; + + public static void main(String argv[]) throws Exception { + + TestKGParity test = new TestKGParity(); + test.run(); + } + + private void run() throws Exception { + Provider[] providers = Security.getProviders(); + for (Provider p : providers) { + String prvName = p.getName(); + if (prvName.startsWith("SunJCE") + || prvName.startsWith("SunPKCS11-")) { + for (String algorithm : ALGORITHM_ARR) { + if (!runTest(p, algorithm)) { + throw new RuntimeException( + "Test failed with provider/algorithm:" + + p.getName() + "/" + algorithm); + } else { + out.println("Test passed with provider/algorithm:" + + p.getName() + "/" + algorithm); + } + } + } + } + } + + public boolean runTest(Provider p, String algo) throws Exception { + byte[] keyValue = null; + try { + // Initialization + SecureRandom sRdm = new SecureRandom(); + KeyGenerator kg = KeyGenerator.getInstance(algo, p); + kg.init(sRdm); + + // Generate a SecretKey and retrieve its value + keyValue = kg.generateKey().getEncoded(); + + // Verify its parity in the unit of byte + for (int i = 0; i < keyValue.length; i++) { + if (!checkParity(keyValue[i])) { + out.println("Testing: " + + p.getName() + + "/" + + algo + + " failed when verify its parity in the unit of byte:" + + TestUtility.hexDump(keyValue, i)); + return false; + } + } + return true; + } catch (Exception ex) { + out.println("Testing: " + p.getName() + "/" + algo + + " failed with unexpected exception"); + ex.printStackTrace(); + throw ex; + } + } + + private boolean checkParity(byte keyByte) { + boolean even = false; + byte[] PARITY_BIT_MASK = { + (byte) 0x40, (byte) 0x20, (byte) 0x10, (byte) 0x08, + (byte) 0x04, (byte) 0x02, (byte) 0x01 + }; + + for (int i = 0; i < 7; i++) { + if ((keyByte & PARITY_BIT_MASK[i]) > 0) { + even = !even; + } + } + if (keyByte < 0) { + even = !even; + } + + return even; + } +} diff --git a/jdk/test/javax/management/remote/mandatory/notif/NotificationBufferDeadlockTest.java b/jdk/test/javax/management/remote/mandatory/notif/NotificationBufferDeadlockTest.java index 79b2e970ab0..e0502079951 100644 --- a/jdk/test/javax/management/remote/mandatory/notif/NotificationBufferDeadlockTest.java +++ b/jdk/test/javax/management/remote/mandatory/notif/NotificationBufferDeadlockTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2015, 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 @@ -24,7 +24,8 @@ /* * @test * @bug 6239400 - * @summary Tests NotificationBuffer doesn't hold locks when adding listeners. + * @summary Tests NotificationBuffer doesn't hold locks when adding listeners, + * if test times out then deadlock is suspected. * @author Eamonn McManus * @run clean NotificationBufferDeadlockTest * @run build NotificationBufferDeadlockTest @@ -38,6 +39,7 @@ import java.net.MalformedURLException; import java.util.List; import java.util.Set; import java.util.Vector; +import java.util.concurrent.CountDownLatch; import javax.management.*; import javax.management.remote.*; @@ -173,9 +175,7 @@ public class NotificationBufferDeadlockTest { for (ObjectName name : names) mbsc.invoke(name, "send", null, null); - if (!countListener.waiting(MAX_WAITING_TIME)) { - return "did not get " + names.size() + " notifs as expected\n"; - } + countListener.waiting(); if (!sources.containsAll(names)) return "missing names: " + sources; @@ -202,13 +202,13 @@ public class NotificationBufferDeadlockTest { } }; t.start(); + System.out.println("DeadlockTest-addNotificationListener waiting for the sending thread to die..."); try { - t.join(5000L); + t.join(); //if times out here then deadlock is suspected + System.out.println("DeadlockTest-addNotificationListener OK."); } catch (Exception e) { thisFailure = "Join exception: " + e; } - if (t.isAlive()) - thisFailure = "Deadlock detected"; } public void send() { @@ -244,9 +244,9 @@ public class NotificationBufferDeadlockTest { } }; t.start(); - t.join(5000); - if (t.isAlive()) - failure = "Query deadlock detected"; + System.out.println("CreateDuringQueryInvocationHandler-createMBeanIfQuery waiting for the creating thread to die..."); + t.join(); // if times out here then deadlock is suspected + System.out.println("CreateDuringQueryInvocationHandler-createMBeanIfQuery OK"); } } @@ -264,50 +264,30 @@ public class NotificationBufferDeadlockTest { private static class MyListener implements NotificationListener { public MyListener(int waitNB) { - this.waitNB= waitNB; + count = new CountDownLatch(waitNB); } public void handleNotification(Notification n, Object h) { - System.out.println("MyListener got: "+n.getSource()+" "+n.getType()); + System.out.println("MyListener got: " + n.getSource() + " " + n.getType()); - synchronized(this) { - if (TESTING_TYPE.equals(n.getType())) { - sources.add((ObjectName) n.getSource()); - - if (sources.size() == waitNB) { - this.notifyAll(); - } - } + if (TESTING_TYPE.equals(n.getType())) { + sources.add((ObjectName) n.getSource()); + count.countDown(); } } - public boolean waiting(long timeout) { - final long startTime = System.currentTimeMillis(); - long toWait = timeout; - - synchronized(this) { - while(sources.size() < waitNB && toWait > 0) { - try { - this.wait(toWait); - } catch (InterruptedException ire) { - break; - } - - toWait = timeout - - (System.currentTimeMillis() - startTime); - } - } - - return sources.size() == waitNB; + public void waiting() throws InterruptedException { + System.out.println("MyListener-waiting ..."); + count.await(); // if times out here then deadlock is suspected + System.out.println("MyListener-waiting done!"); } - private final int waitNB; + private final CountDownLatch count; } static String thisFailure; static String failure; static int nextNameIndex; - static final long MAX_WAITING_TIME = 10000; private static MyListener countListener; private static final List sources = new Vector(); diff --git a/jdk/test/javax/smartcardio/CommandAPDUTest.java b/jdk/test/javax/smartcardio/CommandAPDUTest.java new file mode 100644 index 00000000000..a6ce5c69d41 --- /dev/null +++ b/jdk/test/javax/smartcardio/CommandAPDUTest.java @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2007, 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 8049021 + * @summary Test different constructors for CommandAPDU and check CLA,INS,NC,NE, + * P1,and P2 + * @run testng CommandAPDUTest + */ +import java.nio.ByteBuffer; +import javax.smartcardio.CommandAPDU; +import static org.testng.Assert.*; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +public class CommandAPDUTest { + + static final byte[] C1 = {(byte) 0x00, (byte) 0xA4, (byte) 0x04, + (byte) 0x00, (byte) 0x07, (byte) 0xA0, (byte) 0x00, (byte) 0x00, + (byte) 0x00, (byte) 0x62, (byte) 0x81, (byte) 0x01, (byte) 0x00}; + static int cla, ins, nc, ne, p1, p2; + static byte[] apdu, data; + static CommandAPDU cm1, cm2, cm3, cm4, cm5, cm6, cm7, cm8, cm9; + + @BeforeClass + public static void setUpClass() throws Exception { + //expected values of apdu, data, headers, nc, ne + CommandAPDU capdu = new CommandAPDU(C1); + apdu = capdu.getBytes(); + data = capdu.getData(); + + cla = capdu.getCLA(); + if (cla != (C1[0] & 0xff)) { + throw new RuntimeException("Failure: cla is not right"); + } + + ins = capdu.getINS(); + if (ins != (C1[1] & 0xff)) { + throw new RuntimeException("Failure: ins is not right"); + } + + p1 = capdu.getP1(); + if (p1 != (C1[2] & 0xff)) { + throw new RuntimeException("Failure: p1 is not right"); + } + + p2 = capdu.getP2(); + if (p2 != (C1[3] & 0xff)) { + throw new RuntimeException("Failure: p2 is not right"); + } + + nc = capdu.getNc(); + ne = capdu.getNe(); + + //Test on following constructors + cm1 = new CommandAPDU(apdu); + cm2 = new CommandAPDU(cla, ins, p1, p2); + cm3 = new CommandAPDU(cla, ins, p1, p2, data); + cm4 = new CommandAPDU(cla, ins, p1, p2, data, ne); + cm5 = new CommandAPDU(cla, ins, p1, p2, ne); + cm6 = new CommandAPDU(ByteBuffer.wrap(apdu)); + cm7 = new CommandAPDU(apdu, 0, apdu.length); + cm8 = new CommandAPDU(cla, ins, p1, p2, data, 0, nc); + cm9 = new CommandAPDU(cla, ins, p1, p2, data, 0, nc, ne); + } + + @Test(dataProvider = "provider1") + public static void testHeaders(CommandAPDU cm) { + assertEquals(cla, cm.getCLA()); + assertEquals(ins, cm.getINS()); + assertEquals(p1, cm.getP1()); + assertEquals(p2, cm.getP2()); + } + + @Test(dataProvider = "provider2") + public static void testAPDU(CommandAPDU cm) { + assertEquals(apdu, cm.getBytes()); + } + + @Test(dataProvider = "provider3") + public static void testData(CommandAPDU cm) { + assertEquals(data, cm.getData()); + } + + @Test(dataProvider = "provider3") + public static void testNC(CommandAPDU cm) { + assertEquals(nc, cm.getNc()); + } + + @Test(dataProvider = "provider4") + public static void testNE(CommandAPDU cm) { + assertEquals(ne, cm.getNe()); + } + + @DataProvider + public Object[][] provider1() { + return new Object[][]{{cm1}, {cm2}, {cm3}, {cm4}, {cm5}, {cm6}, {cm7}, + {cm8}, {cm9}}; + } + + @DataProvider + public Object[][] provider2() { + return new Object[][]{{cm1}, {cm6}, {cm7}}; + } + + @DataProvider + public Object[][] provider3() { + return new Object[][]{{cm1}, {cm3}, {cm4}, {cm6}, {cm7}, {cm8}, {cm9}}; + } + + @DataProvider + public Object[][] provider4() { + return new Object[][]{{cm1}, {cm4}, {cm5}, {cm6}, {cm7}, {cm9}}; + } + +} diff --git a/jdk/test/javax/smartcardio/ResponseAPDUTest.java b/jdk/test/javax/smartcardio/ResponseAPDUTest.java new file mode 100644 index 00000000000..995cd1241cf --- /dev/null +++ b/jdk/test/javax/smartcardio/ResponseAPDUTest.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2007, 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 8049021 + * @summary Construct ResponseAPDU from byte array and check NR< SW, SW1 and SW2 + * @run testng ResponseAPDUTest + */ +import javax.smartcardio.ResponseAPDU; +import static org.testng.Assert.*; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +public class ResponseAPDUTest { + + static final byte[] R1 = {(byte) 0x07, (byte) 0xA0, (byte) 0x00, + (byte) 0x00, (byte) 0x00, (byte) 0x62, (byte) 0x81, (byte) 0x01, + (byte) 0x04, (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x24, + (byte) 0x05, (byte) 0x00, (byte) 0x0B, (byte) 0x04, (byte) 0xB0, + (byte) 0x25, (byte) 0x90, (byte) 0x00}; + static final ResponseAPDU RAPDU = new ResponseAPDU(R1); + static byte[] expectedData; + static int expectedNr, expectedSw1, expectedSw2, expectedSw; + + @BeforeClass + public static void setUpClass() throws Exception { + //expected values for data,nr,sw1,sw2 and sw + + int apduLen = R1.length; + expectedData = new byte[apduLen - 2]; + for (int i = 0; i < (apduLen - 2); i++) { + expectedData[i] = R1[i]; + } + + expectedNr = expectedData.length; + expectedSw1 = R1[apduLen - 2] & 0xff; + expectedSw2 = R1[apduLen - 1] & 0xff; + expectedSw = (expectedSw1 << 8) | expectedSw2; + } + + @Test + public static void test() { + assertEquals(RAPDU.getBytes(), R1); + assertEquals(RAPDU.getData(), expectedData); + assertEquals(RAPDU.getNr(), expectedNr); + assertEquals(RAPDU.getSW(), expectedSw); + assertEquals(RAPDU.getSW1(), expectedSw1); + assertEquals(RAPDU.getSW2(), expectedSw2); + } +} diff --git a/jdk/test/javax/smartcardio/TerminalFactorySpiTest.java b/jdk/test/javax/smartcardio/TerminalFactorySpiTest.java new file mode 100644 index 00000000000..cec4c4443e4 --- /dev/null +++ b/jdk/test/javax/smartcardio/TerminalFactorySpiTest.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2007, 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 8049021 + * @summary Test if we can write new provider for smart card + * @run main/othervm/policy=policy TerminalFactorySpiTest + */ +import java.security.Provider; +import java.security.Security; +import java.util.Arrays; +import javax.smartcardio.CardTerminals; +import javax.smartcardio.TerminalFactory; +import javax.smartcardio.TerminalFactorySpi; + +public class TerminalFactorySpiTest { + + static boolean callMethod = false; + + public static void main(String[] args) throws Exception { + Provider myProvider = new MyProvider(); + Security.addProvider(myProvider); + System.out.println(Arrays.asList(Security.getProviders())); + + TerminalFactory.getInstance("MyType", new Object()).terminals(); + if (!callMethod) { + throw new RuntimeException("Expected engineTerminals() not called"); + } + } + + public static class MyProvider extends Provider { + + MyProvider() { + super("MyProvider", 1.0d, "smart Card Example"); + put("TerminalFactory.MyType", "TerminalFactorySpiTest$MyTerminalFactorySpi"); + } + } + + public static class MyTerminalFactorySpi extends TerminalFactorySpi { + + public MyTerminalFactorySpi(Object ob) { + } + + protected CardTerminals engineTerminals() { + System.out.println("MyTerminalFactory.engineTerminals()"); + callMethod = true; + return null; + } + + } +} diff --git a/jdk/test/javax/smartcardio/policy b/jdk/test/javax/smartcardio/policy new file mode 100644 index 00000000000..1df892e4c7b --- /dev/null +++ b/jdk/test/javax/smartcardio/policy @@ -0,0 +1,4 @@ +grant { + permission java.security.SecurityPermission "insertProvider.MyProvider"; + permission java.security.SecurityPermission "putProviderProperty.MyProvider"; +}; diff --git a/jdk/test/lib/testlibrary/jdk/testlibrary/FilterClassLoader.java b/jdk/test/lib/testlibrary/jdk/testlibrary/FilterClassLoader.java new file mode 100644 index 00000000000..fc4e82857f4 --- /dev/null +++ b/jdk/test/lib/testlibrary/jdk/testlibrary/FilterClassLoader.java @@ -0,0 +1,49 @@ +/* + * 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. + */ +package jdk.testlibrary; + +import java.util.function.Predicate; +/** + * A classloader, which using target classloader in case provided condition + * for class name is met, and using parent otherwise + */ +public class FilterClassLoader extends ClassLoader { + + private final ClassLoader target; + private final Predicate condition; + + public FilterClassLoader(ClassLoader target, ClassLoader parent, + Predicate condition) { + super(parent); + this.condition = condition; + this.target = target; + } + + @Override + public Class loadClass(String name) throws ClassNotFoundException { + if (condition.test(name)) { + return target.loadClass(name); + } + return super.loadClass(name); + } +} diff --git a/jdk/test/lib/testlibrary/jdk/testlibrary/ParentLastURLClassLoader.java b/jdk/test/lib/testlibrary/jdk/testlibrary/ParentLastURLClassLoader.java new file mode 100644 index 00000000000..203db612bf3 --- /dev/null +++ b/jdk/test/lib/testlibrary/jdk/testlibrary/ParentLastURLClassLoader.java @@ -0,0 +1,50 @@ +/* + * 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. + */ +package jdk.testlibrary; + +import java.net.URL; +import java.net.URLClassLoader; + +/** + * An url classloader, which trying to load class from provided URL[] first, + * and using parent classloader in case it failed + */ +public class ParentLastURLClassLoader extends URLClassLoader { + + public ParentLastURLClassLoader(URL urls[], ClassLoader parent) { + super(urls, parent); + } + + @Override + public Class loadClass(String name) throws ClassNotFoundException { + try { + Class c = findClass(name); + if (c != null) { + return c; + } + } catch (ClassNotFoundException e) { + // ignore + } + return super.loadClass(name); + } +} diff --git a/jdk/test/lib/testlibrary/jdk/testlibrary/Platform.java b/jdk/test/lib/testlibrary/jdk/testlibrary/Platform.java index 6b92c28f057..6382e01c962 100644 --- a/jdk/test/lib/testlibrary/jdk/testlibrary/Platform.java +++ b/jdk/test/lib/testlibrary/jdk/testlibrary/Platform.java @@ -28,6 +28,15 @@ public class Platform { private static final String dataModel = System.getProperty("sun.arch.data.model"); private static final String vmVersion = System.getProperty("java.vm.version"); private static final String osArch = System.getProperty("os.arch"); + private static final String vmName = System.getProperty("java.vm.name"); + + public static boolean isClient() { + return vmName.endsWith(" Client VM"); + } + + public static boolean isServer() { + return vmName.endsWith(" Server VM"); + } public static boolean is32bit() { return dataModel.equals("32"); diff --git a/jdk/test/lib/testlibrary/jdk/testlibrary/Utils.java b/jdk/test/lib/testlibrary/jdk/testlibrary/Utils.java index af8cc267493..85081f42719 100644 --- a/jdk/test/lib/testlibrary/jdk/testlibrary/Utils.java +++ b/jdk/test/lib/testlibrary/jdk/testlibrary/Utils.java @@ -39,6 +39,7 @@ import java.util.Collections; import java.util.regex.Pattern; import java.util.regex.Matcher; import java.util.concurrent.TimeUnit; +import java.util.function.BooleanSupplier; /** * Common library for various test helper functions. @@ -270,25 +271,6 @@ public final class Utils { } } - /** - * Returns file content as a list of strings - * - * @param file File to operate on - * @return List of strings - * @throws IOException - */ - public static List fileAsList(File file) throws IOException { - assertTrue(file.exists() && file.isFile(), - file.getAbsolutePath() + " does not exist or not a file"); - List output = new ArrayList<>(); - try (BufferedReader reader = new BufferedReader(new FileReader(file.getAbsolutePath()))) { - while (reader.ready()) { - output.add(reader.readLine().replace(NEW_LINE, "")); - } - } - return output; - } - /** * Adjusts the provided timeout value for the TIMEOUT_FACTOR * @param tOut the timeout value to be adjusted @@ -298,4 +280,50 @@ public final class Utils { public static long adjustTimeout(long tOut) { return Math.round(tOut * Utils.TIMEOUT_FACTOR); } + + /** + * Wait for condition to be true + * + * @param condition, a condition to wait for + */ + public static final void waitForCondition(BooleanSupplier condition) { + waitForCondition(condition, -1L, 100L); + } + + /** + * Wait until timeout for condition to be true + * + * @param condition, a condition to wait for + * @param timeout a time in milliseconds to wait for condition to be true + * specifying -1 will wait forever + * @return condition value, to determine if wait was successfull + */ + public static final boolean waitForCondition(BooleanSupplier condition, + long timeout) { + return waitForCondition(condition, timeout, 100L); + } + + /** + * Wait until timeout for condition to be true for specified time + * + * @param condition, a condition to wait for + * @param timeout a time in milliseconds to wait for condition to be true, + * specifying -1 will wait forever + * @param sleepTime a time to sleep value in milliseconds + * @return condition value, to determine if wait was successfull + */ + public static final boolean waitForCondition(BooleanSupplier condition, + long timeout, long sleepTime) { + long startTime = System.currentTimeMillis(); + while (!(condition.getAsBoolean() || (timeout != -1L + && ((System.currentTimeMillis() - startTime) > timeout)))) { + try { + Thread.sleep(sleepTime); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new Error(e); + } + } + return condition.getAsBoolean(); + } } diff --git a/jdk/test/sun/rmi/rmic/iiopCompilation/IIOPCompilation.java b/jdk/test/sun/rmi/rmic/iiopCompilation/IIOPCompilation.java new file mode 100644 index 00000000000..14702b2f471 --- /dev/null +++ b/jdk/test/sun/rmi/rmic/iiopCompilation/IIOPCompilation.java @@ -0,0 +1,96 @@ +/* + * 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 8065957 + * @library ../../../../java/rmi/testlibrary + * @build TestLibrary + * @summary Compiles a PortableRemoteObject with rmic -iiop and ensures that stub and tie classes are generated. + * @run main IIOPCompilation + * @author Felix Yang + * + */ +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.rmi.RemoteException; +import java.util.Arrays; +import java.util.List; + +import javax.rmi.PortableRemoteObject; + +public class IIOPCompilation { + + public static void main(String args[]) throws IOException, InterruptedException { + IIOPCompilation test = new IIOPCompilation(); + test.doTest(); + } + + private void doTest() throws IOException, InterruptedException { + String className = DummyImpl.class.getName(); + int exitCode = runRmic(className); + if (exitCode != 0) { + throw new RuntimeException("Rmic failed. The exit code is " + exitCode); + } + + // Check the stub class generated correctly + String stubFile = "_" + Dummy.class.getName() + "_Stub.class"; + assertFileExists(stubFile); + + // Check the tie class generated correctly + String tieFile = "_" + className + "_Tie.class"; + assertFileExists(tieFile); + } + + private void assertFileExists(String fileName) throws FileNotFoundException { + if (!new File(fileName).exists()) { + throw new FileNotFoundException(fileName + " doesn't exist!"); + } + } + + private int runRmic(String classname) throws IOException, InterruptedException { + String rmicProgramStr = TestLibrary.getProperty("java.home", "") + File.separator + "bin" + File.separator + "rmic"; + String testClasses = TestLibrary.getProperty("test.classes", ""); + List command = Arrays.asList(rmicProgramStr, "-iiop", "-classpath", testClasses, classname); + System.out.println("Running command: " + command); + + Process p = null; + try { + p = new ProcessBuilder(command).inheritIO().start(); + p.waitFor(); + return p.exitValue(); + } finally { + if (p != null && p.isAlive()) { + p.destroy(); + } + } + } +} + +interface Dummy extends java.rmi.Remote { +} + +class DummyImpl extends PortableRemoteObject implements Dummy { + public DummyImpl() throws RemoteException { + } +} diff --git a/jdk/test/sun/security/provider/DSA/TestDSA2.java b/jdk/test/sun/security/provider/DSA/TestDSA2.java index a478b8bc0a3..20e6552f85a 100644 --- a/jdk/test/sun/security/provider/DSA/TestDSA2.java +++ b/jdk/test/sun/security/provider/DSA/TestDSA2.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -50,7 +50,7 @@ public class TestDSA2 { public static void main(String[] args) throws Exception { boolean[] expectedToPass = { true, true, true }; test(1024, expectedToPass); - boolean[] expectedToPass2 = { false, true, true }; + boolean[] expectedToPass2 = { true, true, true }; test(2048, expectedToPass2); } diff --git a/jdk/test/sun/tools/jcmd/TestJcmdDefaults.java b/jdk/test/sun/tools/jcmd/TestJcmdDefaults.java index 2292be403da..c13b4d5da11 100644 --- a/jdk/test/sun/tools/jcmd/TestJcmdDefaults.java +++ b/jdk/test/sun/tools/jcmd/TestJcmdDefaults.java @@ -25,6 +25,9 @@ import static jdk.testlibrary.Asserts.*; import java.io.File; import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.List; import jdk.testlibrary.JcmdBase; @@ -95,11 +98,11 @@ public class TestJcmdDefaults { } private static void verifyOutputAgainstFile(OutputAnalyzer output) throws IOException { - File file = new File(TEST_SRC, "usage.out"); - List fileOutput = Utils.fileAsList(file); + Path path = Paths.get(TEST_SRC, "usage.out"); + List fileOutput = Files.readAllLines(path); List outputAsLines = output.asLines(); assertTrue(outputAsLines.containsAll(fileOutput), - "The ouput should contain all content of " + file.getAbsolutePath()); + "The ouput should contain all content of " + path.toAbsolutePath()); } } diff --git a/jdk/test/sun/tools/jcmd/TestJcmdSanity.java b/jdk/test/sun/tools/jcmd/TestJcmdSanity.java index 89152216010..8479730f52c 100644 --- a/jdk/test/sun/tools/jcmd/TestJcmdSanity.java +++ b/jdk/test/sun/tools/jcmd/TestJcmdSanity.java @@ -25,6 +25,9 @@ import static jdk.testlibrary.Asserts.*; import java.io.File; import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.List; import jdk.testlibrary.JcmdBase; @@ -160,11 +163,11 @@ public class TestJcmdSanity { } private static void verifyOutputAgainstFile(OutputAnalyzer output) throws IOException { - File file = new File(TEST_SRC, "help_help.out"); - List fileOutput = Utils.fileAsList(file); + Path path = Paths.get(TEST_SRC, "help_help.out"); + List fileOutput = Files.readAllLines(path); List outputAsLines = output.asLines(); assertTrue(outputAsLines.containsAll(fileOutput), - "The ouput should contain all content of " + file.getAbsolutePath()); + "The ouput should contain all content of " + path.toAbsolutePath()); } } diff --git a/jdk/test/sun/tools/jps/JpsHelper.java b/jdk/test/sun/tools/jps/JpsHelper.java index 079ae03d67e..e28e92dae73 100644 --- a/jdk/test/sun/tools/jps/JpsHelper.java +++ b/jdk/test/sun/tools/jps/JpsHelper.java @@ -28,6 +28,9 @@ import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -189,11 +192,11 @@ public final class JpsHelper { */ public static void verifyOutputAgainstFile(OutputAnalyzer output) throws IOException { String testSrc = System.getProperty("test.src", "?"); - File file = new File(testSrc, "usage.out"); - List fileOutput = Utils.fileAsList(file); + Path path = Paths.get(testSrc, "usage.out"); + List fileOutput = Files.readAllLines(path); List outputAsLines = output.asLines(); assertTrue(outputAsLines.containsAll(fileOutput), - "The ouput should contain all content of " + file.getAbsolutePath()); + "The ouput should contain all content of " + path.toAbsolutePath()); } private static File getManifest(String className) throws IOException { diff --git a/jdk/test/tools/pack200/Pack200Test.java b/jdk/test/tools/pack200/Pack200Test.java index 69cec754a07..3b1e5ca86b3 100644 --- a/jdk/test/tools/pack200/Pack200Test.java +++ b/jdk/test/tools/pack200/Pack200Test.java @@ -127,7 +127,7 @@ public class Pack200Test { // select the jars carefully, adding more jars will increase the // testing time, especially for jprt. jarList.add(Utils.createRtJar()); - jarList.add(Utils.locateJar("golden.jar")); + jarList.add(Utils.getGoldenJar()); System.out.println(jarList); doPackUnpack(); } diff --git a/jdk/test/tools/pack200/PackTestZip64.java b/jdk/test/tools/pack200/PackTestZip64.java index edfeb5a92d8..bd2fece8b8b 100644 --- a/jdk/test/tools/pack200/PackTestZip64.java +++ b/jdk/test/tools/pack200/PackTestZip64.java @@ -52,7 +52,7 @@ public class PackTestZip64 { // make a copy of the test specimen to local directory File testFile = new File("tools_java.jar"); // Add a large number of small files to the golden jar - generateLargeJar(testFile, Utils.locateJar("golden.jar")); + generateLargeJar(testFile, Utils.getGoldenJar()); List cmdsList = new ArrayList<>(); diff --git a/jdk/test/tools/pack200/RepackTest.java b/jdk/test/tools/pack200/RepackTest.java index 8a3d86e7c94..f9d25660431 100644 --- a/jdk/test/tools/pack200/RepackTest.java +++ b/jdk/test/tools/pack200/RepackTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -50,7 +50,7 @@ public class RepackTest { // make a copy of the test specimen to local directory File testFile = new File("src_tools.jar"); - Utils.copyFile(Utils.locateJar("golden.jar"), testFile); + Utils.copyFile(Utils.getGoldenJar(), testFile); List cmdsList = new ArrayList<>(); // case 1: diff --git a/jdk/test/tools/pack200/TimeStamp.java b/jdk/test/tools/pack200/TimeStamp.java index 60e69b726b2..fc16dd06a6b 100644 --- a/jdk/test/tools/pack200/TimeStamp.java +++ b/jdk/test/tools/pack200/TimeStamp.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 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 @@ -54,7 +54,7 @@ public class TimeStamp { public static void main(String... args) throws IOException { // make a local copy of our test file - File srcFile = Utils.locateJar("golden.jar"); + File srcFile = Utils.getGoldenJar(); File goldenFile = new File("golden.jar"); Utils.copyFile(srcFile, goldenFile); diff --git a/jdk/test/tools/pack200/Utils.java b/jdk/test/tools/pack200/Utils.java index c46d2f0ecc4..f0c29a597b5 100644 --- a/jdk/test/tools/pack200/Utils.java +++ b/jdk/test/tools/pack200/Utils.java @@ -63,7 +63,7 @@ class Utils { System.getProperty("os.name").startsWith("Windows"); static final boolean Is64Bit = System.getProperty("sun.arch.data.model", "32").equals("64"); - static final File JavaSDK = new File(JavaHome).getParentFile(); + static final File JavaSDK = new File(JavaHome); static final String PACK_FILE_EXT = ".pack"; static final String JAVA_FILE_EXT = ".java"; @@ -82,11 +82,7 @@ class Utils { if (VerifierJar.exists()) { return; } - File srcDir = new File(TEST_SRC_DIR, VERIFIER_DIR_NAME); - if (!srcDir.exists()) { - // if not available try one level above - srcDir = new File(TEST_SRC_DIR.getParentFile(), VERIFIER_DIR_NAME); - } + File srcDir = new File(getVerifierDir(), "src"); List javaFileList = findFiles(srcDir, createFilter(JAVA_FILE_EXT)); File tmpFile = File.createTempFile("javac", ".tmp"); XCLASSES.mkdirs(); @@ -115,6 +111,18 @@ class Utils { "."); } + private static File getVerifierDir() { + File srcDir = new File(TEST_SRC_DIR, VERIFIER_DIR_NAME); + if (!srcDir.exists()) { + // if not available try one level above + srcDir = new File(TEST_SRC_DIR.getParentFile(), VERIFIER_DIR_NAME); + } + return srcDir; + } + + static File getGoldenJar() { + return new File(new File(getVerifierDir(), "data"), "golden.jar"); + } static void dirlist(File dir) { File[] files = dir.listFiles(); System.out.println("--listing " + dir.getAbsolutePath() + "---"); @@ -564,7 +572,8 @@ class Utils { File rtJar = new File("rt.jar"); cmdList.clear(); cmdList.add(getJarCmd()); - cmdList.add("cvf"); + // cmdList.add("cvf"); too noisy + cmdList.add("cf"); cmdList.add(rtJar.getName()); cmdList.add("-C"); cmdList.add("out"); @@ -574,24 +583,4 @@ class Utils { recursiveDelete(new File("out")); return rtJar; } - private static List locaterCache = null; - // search the source dir and jdk dir for requested file and returns - // the first location it finds. - static File locateJar(String name) { - try { - if (locaterCache == null) { - locaterCache = new ArrayList(); - locaterCache.addAll(findFiles(TEST_SRC_DIR, createFilter(JAR_FILE_EXT))); - locaterCache.addAll(findFiles(JavaSDK, createFilter(JAR_FILE_EXT))); - } - for (File f : locaterCache) { - if (f.getName().equals(name)) { - return f; - } - } - throw new IOException("file not found: " + name); - } catch (IOException e) { - throw new RuntimeException(e); - } - } } diff --git a/langtools/.hgtags b/langtools/.hgtags index 7bd86ea5a39..c7267deceed 100644 --- a/langtools/.hgtags +++ b/langtools/.hgtags @@ -285,3 +285,5 @@ c536541235e566701ff772700c15de14b75e2979 jdk9-b36 c286272a81dd8f6005e22fed0238c4a3f75188c7 jdk9-b40 f7ce2cfa4cdbec0ae0f46080484eace66be7987a jdk9-b41 23a3a063a906a91ba696d792f0eeabf157cd2f86 jdk9-b42 +6a06008aec10d32898ca665685f531c681b28f5f jdk9-b43 +de2ce70d907c9f227b802cea29285bece5194cd5 jdk9-b44 diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Analyzer.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Analyzer.java new file mode 100644 index 00000000000..1eb1ab48808 --- /dev/null +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Analyzer.java @@ -0,0 +1,509 @@ +/* + * 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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. + */ + +package com.sun.tools.javac.comp; + +import com.sun.source.tree.LambdaExpressionTree; +import com.sun.tools.javac.code.Source; +import com.sun.tools.javac.code.Type; +import com.sun.tools.javac.code.Types; +import com.sun.tools.javac.tree.JCTree; +import com.sun.tools.javac.tree.JCTree.JCBlock; +import com.sun.tools.javac.tree.JCTree.JCClassDecl; +import com.sun.tools.javac.tree.JCTree.JCDoWhileLoop; +import com.sun.tools.javac.tree.JCTree.JCEnhancedForLoop; +import com.sun.tools.javac.tree.JCTree.JCForLoop; +import com.sun.tools.javac.tree.JCTree.JCIf; +import com.sun.tools.javac.tree.JCTree.JCLambda; +import com.sun.tools.javac.tree.JCTree.JCLambda.ParameterKind; +import com.sun.tools.javac.tree.JCTree.JCMethodDecl; +import com.sun.tools.javac.tree.JCTree.JCMethodInvocation; +import com.sun.tools.javac.tree.JCTree.JCNewClass; +import com.sun.tools.javac.tree.JCTree.JCStatement; +import com.sun.tools.javac.tree.JCTree.JCSwitch; +import com.sun.tools.javac.tree.JCTree.JCTypeApply; +import com.sun.tools.javac.tree.JCTree.JCVariableDecl; +import com.sun.tools.javac.tree.JCTree.JCWhileLoop; +import com.sun.tools.javac.tree.JCTree.Tag; +import com.sun.tools.javac.tree.TreeCopier; +import com.sun.tools.javac.tree.TreeInfo; +import com.sun.tools.javac.tree.TreeMaker; +import com.sun.tools.javac.tree.TreeScanner; +import com.sun.tools.javac.util.Context; +import com.sun.tools.javac.util.DefinedBy; +import com.sun.tools.javac.util.DefinedBy.Api; +import com.sun.tools.javac.util.Filter; +import com.sun.tools.javac.util.JCDiagnostic; +import com.sun.tools.javac.util.JCDiagnostic.DiagnosticType; +import com.sun.tools.javac.util.List; +import com.sun.tools.javac.util.ListBuffer; +import com.sun.tools.javac.util.Log; +import com.sun.tools.javac.util.Names; +import com.sun.tools.javac.util.Options; + +import java.util.EnumSet; +import java.util.HashMap; +import java.util.Map; +import java.util.function.Predicate; + +import static com.sun.tools.javac.code.Flags.GENERATEDCONSTR; +import static com.sun.tools.javac.code.Flags.SYNTHETIC; +import static com.sun.tools.javac.code.TypeTag.CLASS; +import static com.sun.tools.javac.tree.JCTree.Tag.APPLY; +import static com.sun.tools.javac.tree.JCTree.Tag.CLASSDEF; +import static com.sun.tools.javac.tree.JCTree.Tag.METHODDEF; +import static com.sun.tools.javac.tree.JCTree.Tag.NEWCLASS; +import static com.sun.tools.javac.tree.JCTree.Tag.TYPEAPPLY; + +/** + * Helper class for defining custom code analysis, such as finding instance creation expression + * that can benefit from diamond syntax. + */ +public class Analyzer { + protected static final Context.Key analyzerKey = new Context.Key<>(); + + final Types types; + final Log log; + final Attr attr; + final DeferredAttr deferredAttr; + final TreeMaker make; + final Names names; + + final EnumSet analyzerModes; + + public static Analyzer instance(Context context) { + Analyzer instance = context.get(analyzerKey); + if (instance == null) + instance = new Analyzer(context); + return instance; + } + + protected Analyzer(Context context) { + context.put(analyzerKey, this); + types = Types.instance(context); + log = Log.instance(context); + attr = Attr.instance(context); + deferredAttr = DeferredAttr.instance(context); + make = TreeMaker.instance(context); + names = Names.instance(context); + Options options = Options.instance(context); + String findOpt = options.get("find"); + //parse modes + Source source = Source.instance(context); + analyzerModes = AnalyzerMode.getAnalyzerModes(findOpt, source); + } + + /** + * This enum defines supported analyzer modes, as well as defining the logic for decoding + * the {@code -XDfind} option. + */ + enum AnalyzerMode { + DIAMOND("diamond", Source::allowDiamond), + LAMBDA("lambda", Source::allowLambda), + METHOD("method", Source::allowGraphInference); + + final String opt; + final Predicate sourceFilter; + + AnalyzerMode(String opt, Predicate sourceFilter) { + this.opt = opt; + this.sourceFilter = sourceFilter; + } + + /** + * This method is used to parse the {@code find} option. + * Possible modes are separated by colon; a mode can be excluded by + * prepending '-' to its name. Finally, the special mode 'all' can be used to + * add all modes to the resulting enum. + */ + static EnumSet getAnalyzerModes(String opt, Source source) { + if (opt == null) { + return EnumSet.noneOf(AnalyzerMode.class); + } + List modes = List.from(opt.split(",")); + EnumSet res = EnumSet.noneOf(AnalyzerMode.class); + if (modes.contains("all")) { + res = EnumSet.allOf(AnalyzerMode.class); + } + for (AnalyzerMode mode : values()) { + if (modes.contains(mode.opt)) { + res.add(mode); + } else if (modes.contains("-" + mode.opt) || !mode.sourceFilter.test(source)) { + res.remove(mode); + } + } + return res; + } + } + + /** + * A statement analyzer is a work-unit that matches certain AST nodes (of given type {@code S}), + * rewrites them to different AST nodes (of type {@code T}) and then generates some meaningful + * messages in case the analysis has been successful. + */ + abstract class StatementAnalyzer { + + AnalyzerMode mode; + JCTree.Tag tag; + + StatementAnalyzer(AnalyzerMode mode, Tag tag) { + this.mode = mode; + this.tag = tag; + } + + /** + * Is this analyzer allowed to run? + */ + boolean isEnabled() { + return analyzerModes.contains(mode); + } + + /** + * Should this analyzer be rewriting the given tree? + */ + abstract boolean match(S tree); + + /** + * Rewrite a given AST node into a new one + */ + abstract T map(S oldTree, S newTree); + + /** + * Entry-point for comparing results and generating diagnostics. + */ + abstract void process(S oldTree, T newTree, boolean hasErrors); + + } + + /** + * This analyzer checks if generic instance creation expression can use diamond syntax. + */ + class DiamondInitializer extends StatementAnalyzer { + + DiamondInitializer() { + super(AnalyzerMode.DIAMOND, NEWCLASS); + } + + @Override + boolean match(JCNewClass tree) { + return tree.clazz.hasTag(TYPEAPPLY) && + !TreeInfo.isDiamond(tree) && + tree.def == null; + } + + @Override + JCNewClass map(JCNewClass oldTree, JCNewClass newTree) { + if (newTree.clazz.hasTag(TYPEAPPLY)) { + ((JCTypeApply)newTree.clazz).arguments = List.nil(); + } + return newTree; + } + + @Override + void process(JCNewClass oldTree, JCNewClass newTree, boolean hasErrors) { + if (!hasErrors) { + List inferredArgs = newTree.type.getTypeArguments(); + List explicitArgs = oldTree.type.getTypeArguments(); + for (Type t : inferredArgs) { + if (!types.isSameType(t, explicitArgs.head)) { + log.warning(oldTree.clazz, "diamond.redundant.args.1", + oldTree.clazz.type, newTree.clazz.type); + return; + } + explicitArgs = explicitArgs.tail; + } + //exact match + log.warning(oldTree.clazz, "diamond.redundant.args"); + } + } + } + + /** + * This analyzer checks if anonymous instance creation expression can replaced by lambda. + */ + class LambdaAnalyzer extends StatementAnalyzer { + + LambdaAnalyzer() { + super(AnalyzerMode.LAMBDA, NEWCLASS); + } + + @Override + boolean match (JCNewClass tree){ + Type clazztype = tree.clazz.type; + return tree.def != null && + clazztype.hasTag(CLASS) && + types.isFunctionalInterface(clazztype.tsym) && + decls(tree.def).length() == 1; + } + //where + private List decls(JCClassDecl decl) { + ListBuffer decls = new ListBuffer<>(); + for (JCTree t : decl.defs) { + if (t.hasTag(METHODDEF)) { + JCMethodDecl md = (JCMethodDecl)t; + if ((md.getModifiers().flags & GENERATEDCONSTR) == 0) { + decls.add(md); + } + } else { + decls.add(t); + } + } + return decls.toList(); + } + + @Override + JCLambda map (JCNewClass oldTree, JCNewClass newTree){ + JCMethodDecl md = (JCMethodDecl)decls(newTree.def).head; + List params = md.params; + JCBlock body = md.body; + return make.Lambda(params, body); + } + @Override + void process (JCNewClass oldTree, JCLambda newTree, boolean hasErrors){ + if (!hasErrors) { + log.warning(oldTree.def, "potential.lambda.found"); + } + } + } + + /** + * This analyzer checks if generic method call has redundant type arguments. + */ + class RedundantTypeArgAnalyzer extends StatementAnalyzer { + + RedundantTypeArgAnalyzer() { + super(AnalyzerMode.METHOD, APPLY); + } + + @Override + boolean match (JCMethodInvocation tree){ + return tree.typeargs != null && + tree.typeargs.nonEmpty(); + } + @Override + JCMethodInvocation map (JCMethodInvocation oldTree, JCMethodInvocation newTree){ + newTree.typeargs = List.nil(); + return newTree; + } + @Override + void process (JCMethodInvocation oldTree, JCMethodInvocation newTree, boolean hasErrors){ + if (!hasErrors) { + //exact match + log.warning(oldTree, "method.redundant.typeargs"); + } + } + } + + @SuppressWarnings({"unchecked", "rawtypes"}) + StatementAnalyzer[] analyzers = new StatementAnalyzer[] { + new DiamondInitializer(), + new LambdaAnalyzer(), + new RedundantTypeArgAnalyzer() + }; + + /** + * Analyze an AST node if needed. + */ + void analyzeIfNeeded(JCTree tree, Env env) { + if (!analyzerModes.isEmpty() && + !env.info.isSpeculative && + TreeInfo.isStatement(tree)) { + JCStatement stmt = (JCStatement)tree; + analyze(stmt, env); + } + } + + /** + * Analyze an AST node; this involves collecting a list of all the nodes that needs rewriting, + * and speculatively type-check the rewritten code to compare results against previously attributed code. + */ + void analyze(JCStatement statement, Env env) { + AnalysisContext context = new AnalysisContext(); + StatementScanner statementScanner = new StatementScanner(context); + statementScanner.scan(statement); + + if (!context.treesToAnalyzer.isEmpty()) { + + //add a block to hoist potential dangling variable declarations + JCBlock fakeBlock = make.Block(SYNTHETIC, List.of(statement)); + + TreeMapper treeMapper = new TreeMapper(context); + //TODO: to further refine the analysis, try all rewriting combinations + deferredAttr.attribSpeculative(fakeBlock, env, attr.statInfo, treeMapper, + t -> new AnalyzeDeferredDiagHandler(context)); + + context.treeMap.entrySet().forEach(e -> { + context.treesToAnalyzer.get(e.getKey()) + .process(e.getKey(), e.getValue(), context.errors.nonEmpty()); + }); + } + } + + /** + * Simple deferred diagnostic handler which filters out all messages and keep track of errors. + */ + class AnalyzeDeferredDiagHandler extends Log.DeferredDiagnosticHandler { + AnalysisContext context; + + public AnalyzeDeferredDiagHandler(AnalysisContext context) { + super(log, d -> { + if (d.getType() == DiagnosticType.ERROR) { + context.errors.add(d); + } + return true; + }); + this.context = context; + } + } + + /** + * This class is used to pass around contextual information bewteen analyzer classes, such as + * trees to be rewritten, errors occurred during the speculative attribution step, etc. + */ + class AnalysisContext { + /** Map from trees to analyzers. */ + Map> treesToAnalyzer = new HashMap<>(); + + /** Map from original AST nodes to rewritten AST nodes */ + Map treeMap = new HashMap<>(); + + /** Errors in rewritten tree */ + ListBuffer errors = new ListBuffer<>(); + } + + /** + * Subclass of {@link com.sun.tools.javac.tree.TreeScanner} which visit AST-nodes w/o crossing + * statement boundaries. + */ + class StatementScanner extends TreeScanner { + + /** context */ + AnalysisContext context; + + StatementScanner(AnalysisContext context) { + this.context = context; + } + + @Override + @SuppressWarnings("unchecked") + public void scan(JCTree tree) { + if (tree != null) { + for (StatementAnalyzer analyzer : analyzers) { + if (analyzer.isEnabled() && + tree.hasTag(analyzer.tag) && + analyzer.match(tree)) { + context.treesToAnalyzer.put(tree, analyzer); + break; //TODO: cover cases where multiple matching analyzers are found + } + } + } + super.scan(tree); + } + + @Override + public void visitClassDef(JCClassDecl tree) { + //do nothing (prevents seeing same stuff twice + } + + @Override + public void visitMethodDef(JCMethodDecl tree) { + //do nothing (prevents seeing same stuff twice + } + + @Override + public void visitBlock(JCBlock tree) { + //do nothing (prevents seeing same stuff twice + } + + @Override + public void visitSwitch(JCSwitch tree) { + scan(tree.getExpression()); + } + + @Override + public void visitForLoop(JCForLoop tree) { + scan(tree.getInitializer()); + scan(tree.getCondition()); + scan(tree.getUpdate()); + } + + @Override + public void visitForeachLoop(JCEnhancedForLoop tree) { + scan(tree.getExpression()); + } + + @Override + public void visitWhileLoop(JCWhileLoop tree) { + scan(tree.getCondition()); + } + + @Override + public void visitDoLoop(JCDoWhileLoop tree) { + scan(tree.getCondition()); + } + + @Override + public void visitIf(JCIf tree) { + scan(tree.getCondition()); + } + } + + /** + * Subclass of TreeCopier that maps nodes matched by analyzers onto new AST nodes. + */ + class TreeMapper extends TreeCopier { + + AnalysisContext context; + + TreeMapper(AnalysisContext context) { + super(make); + this.context = context; + } + + @Override + @SuppressWarnings("unchecked") + public Z copy(Z tree, Void _unused) { + Z newTree = super.copy(tree, _unused); + StatementAnalyzer analyzer = context.treesToAnalyzer.get(tree); + if (analyzer != null) { + newTree = (Z)analyzer.map(tree, newTree); + context.treeMap.put(tree, newTree); + } + return newTree; + } + + @Override @DefinedBy(Api.COMPILER_TREE) + public JCTree visitLambdaExpression(LambdaExpressionTree node, Void _unused) { + JCLambda oldLambda = (JCLambda)node; + JCLambda newLambda = (JCLambda)super.visitLambdaExpression(node, _unused); + if (oldLambda.paramKind == ParameterKind.IMPLICIT) { + //reset implicit lambda parameters (whose type might have been set during attr) + newLambda.paramKind = ParameterKind.IMPLICIT; + newLambda.params.forEach(p -> p.vartype = null); + } + return newLambda; + } + } +} diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java index d6aa70a00d1..7ea795423d0 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java @@ -83,6 +83,7 @@ public class Attr extends JCTree.Visitor { final Symtab syms; final Resolve rs; final Infer infer; + final Analyzer analyzer; final DeferredAttr deferredAttr; final Check chk; final Flow flow; @@ -121,6 +122,7 @@ public class Attr extends JCTree.Visitor { make = TreeMaker.instance(context); enter = Enter.instance(context); infer = Infer.instance(context); + analyzer = Analyzer.instance(context); deferredAttr = DeferredAttr.instance(context); cfolder = ConstFold.instance(context); target = Target.instance(context); @@ -143,11 +145,8 @@ public class Attr extends JCTree.Visitor { allowStaticInterfaceMethods = source.allowStaticInterfaceMethods(); sourceName = source.name; relax = (options.isSet("-retrofit") || - options.isSet("-relax")); - findDiamonds = options.get("findDiamond") != null && - source.allowDiamond(); + options.isSet("-relax")); useBeforeDeclarationWarning = options.isSet("useBeforeDeclarationWarning"); - identifyLambdaCandidate = options.getBoolean("identifyLambdaCandidate", false); statInfo = new ResultInfo(KindSelector.NIL, Type.noType); varAssignmentInfo = new ResultInfo(KindSelector.ASG, Type.noType); @@ -156,6 +155,8 @@ public class Attr extends JCTree.Visitor { unknownTypeInfo = new ResultInfo(KindSelector.TYP, Type.noType); unknownTypeExprInfo = new ResultInfo(KindSelector.VAL_TYP, Type.noType); recoveryInfo = new RecoveryInfo(deferredAttr.emptyDeferredAttrContext); + + noCheckTree = make.at(-1).Skip(); } /** Switch: relax some constraints for retrofit mode. @@ -182,28 +183,12 @@ public class Attr extends JCTree.Visitor { */ boolean allowStaticInterfaceMethods; - /** Switch: generates a warning if diamond can be safely applied - * to a given new expression - */ - boolean findDiamonds; - - /** - * Internally enables/disables diamond finder feature - */ - static final boolean allowDiamondFinder = true; - /** * Switch: warn about use of variable before declaration? * RFE: 6425594 */ boolean useBeforeDeclarationWarning; - /** - * Switch: generate warnings whenever an anonymous inner class that is convertible - * to a lambda expression is found - */ - boolean identifyLambdaCandidate; - /** * Switch: allow strings in switch? */ @@ -231,31 +216,32 @@ public class Attr extends JCTree.Visitor { final ResultInfo resultInfo) { InferenceContext inferenceContext = resultInfo.checkContext.inferenceContext(); Type owntype; - if (!found.hasTag(ERROR) && !resultInfo.pt.hasTag(METHOD) && !resultInfo.pt.hasTag(FORALL)) { - if (!ownkind.subset(resultInfo.pkind)) { - log.error(tree.pos(), "unexpected.type", - resultInfo.pkind.kindNames(), - ownkind.kindNames()); - owntype = types.createErrorType(found); - } else if (allowPoly && inferenceContext.free(found)) { - //delay the check if there are inference variables in the found type - //this means we are dealing with a partially inferred poly expression - owntype = resultInfo.pt; - inferenceContext.addFreeTypeListener(List.of(found, resultInfo.pt), new FreeTypeListener() { - @Override - public void typesInferred(InferenceContext inferenceContext) { + boolean shouldCheck = !found.hasTag(ERROR) && + !resultInfo.pt.hasTag(METHOD) && + !resultInfo.pt.hasTag(FORALL); + if (shouldCheck && !ownkind.subset(resultInfo.pkind)) { + log.error(tree.pos(), "unexpected.type", + resultInfo.pkind.kindNames(), + ownkind.kindNames()); + owntype = types.createErrorType(found); + } else if (allowPoly && inferenceContext.free(found)) { + //delay the check if there are inference variables in the found type + //this means we are dealing with a partially inferred poly expression + owntype = shouldCheck ? resultInfo.pt : found; + inferenceContext.addFreeTypeListener(List.of(found, resultInfo.pt), + instantiatedContext -> { ResultInfo pendingResult = resultInfo.dup(inferenceContext.asInstType(resultInfo.pt)); check(tree, inferenceContext.asInstType(found), ownkind, pendingResult); - } - }); - } else { - owntype = resultInfo.check(tree, found); - } + }); } else { - owntype = found; + owntype = shouldCheck ? + resultInfo.check(tree, found) : + found; + } + if (tree != noCheckTree) { + tree.type = owntype; } - tree.type = owntype; return owntype; } @@ -531,6 +517,10 @@ public class Attr extends JCTree.Visitor { */ Type result; + /** Synthetic tree to be used during 'fake' checks. + */ + JCTree noCheckTree; + /** Visitor method: attribute a tree, catching any completion failure * exceptions. Return the tree's type. * @@ -610,7 +600,13 @@ public class Attr extends JCTree.Visitor { /** Derived visitor method: attribute a statement or definition tree. */ public Type attribStat(JCTree tree, Env env) { - return attribTree(tree, env, statInfo); + Env analyzeEnv = + env.dup(tree, env.info.dup(env.info.scope.dupUnshared(env.info.scope.owner))); + try { + return attribTree(tree, env, statInfo); + } finally { + analyzer.analyzeIfNeeded(tree, analyzeEnv); + } } /** Attribute a list of expressions, returning a list of types. @@ -792,8 +788,8 @@ public class Attr extends JCTree.Visitor { Type attribIdentAsEnumType(Env env, JCIdent id) { Assert.check((env.enclClass.sym.flags() & ENUM) != 0); - id.type = env.info.scope.owner.type; - id.sym = env.info.scope.owner; + id.type = env.info.scope.owner.enclClass().type; + id.sym = env.info.scope.owner.enclClass(); return id.type; } @@ -2018,7 +2014,7 @@ public class Attr extends JCTree.Visitor { } }); Type constructorType = tree.constructorType = types.createErrorType(clazztype); - constructorType = checkId(tree, site, + constructorType = checkId(noCheckTree, site, constructor, diamondEnv, diamondResult); @@ -2044,7 +2040,7 @@ public class Attr extends JCTree.Visitor { tree.constructor = rs.resolveConstructor( tree.pos(), rsEnv, clazztype, argtypes, typeargtypes); if (cdef == null) { //do not check twice! - tree.constructorType = checkId(tree, + tree.constructorType = checkId(noCheckTree, clazztype, tree.constructor, rsEnv, @@ -2052,12 +2048,6 @@ public class Attr extends JCTree.Visitor { if (rsEnv.info.lastResolveVarargs()) Assert.check(tree.constructorType.isErroneous() || tree.varargsElement != null); } - if (cdef == null && - !clazztype.isErroneous() && - clazztype.getTypeArguments().nonEmpty() && - findDiamonds) { - findDiamond(localEnv, tree, clazztype); - } } if (cdef != null) { @@ -2105,8 +2095,6 @@ public class Attr extends JCTree.Visitor { attribStat(cdef, localEnv); - checkLambdaCandidate(tree, cdef.sym, clazztype); - // If an outer instance is given, // prefix it to the constructor arguments // and delete it from the new expression @@ -2122,7 +2110,7 @@ public class Attr extends JCTree.Visitor { tree.pos(), localEnv, clazztype, argtypes, typeargtypes); Assert.check(!sym.kind.isOverloadError()); tree.constructor = sym; - tree.constructorType = checkId(tree, + tree.constructorType = checkId(noCheckTree, clazztype, tree.constructor, localEnv, @@ -2133,60 +2121,16 @@ public class Attr extends JCTree.Visitor { owntype = clazztype; } result = check(tree, owntype, KindSelector.VAL, resultInfo); + InferenceContext inferenceContext = resultInfo.checkContext.inferenceContext(); + if (tree.constructorType != null && inferenceContext.free(tree.constructorType)) { + //we need to wait for inference to finish and then replace inference vars in the constructor type + inferenceContext.addFreeTypeListener(List.of(tree.constructorType), + instantiatedContext -> { + tree.constructorType = instantiatedContext.asInstType(tree.constructorType); + }); + } chk.validate(tree.typeargs, localEnv); } - //where - void findDiamond(Env env, JCNewClass tree, Type clazztype) { - JCTypeApply ta = (JCTypeApply)tree.clazz; - List prevTypeargs = ta.arguments; - try { - //create a 'fake' diamond AST node by removing type-argument trees - ta.arguments = List.nil(); - ResultInfo findDiamondResult = new ResultInfo(KindSelector.VAL, - resultInfo.checkContext.inferenceContext().free(resultInfo.pt) ? Type.noType : pt()); - Type inferred = deferredAttr.attribSpeculative(tree, env, findDiamondResult).type; - Type polyPt = allowPoly ? - syms.objectType : - clazztype; - if (!inferred.isErroneous() && - (allowPoly && pt() == Infer.anyPoly ? - types.isSameType(inferred, clazztype) : - types.isAssignable(inferred, pt().hasTag(NONE) ? polyPt : pt(), types.noWarnings))) { - String key = types.isSameType(clazztype, inferred) ? - "diamond.redundant.args" : - "diamond.redundant.args.1"; - log.warning(tree.clazz.pos(), key, clazztype, inferred); - } - } finally { - ta.arguments = prevTypeargs; - } - } - - private void checkLambdaCandidate(JCNewClass tree, ClassSymbol csym, Type clazztype) { - if (allowLambda && - identifyLambdaCandidate && - clazztype.hasTag(CLASS) && - !pt().hasTag(NONE) && - types.isFunctionalInterface(clazztype.tsym)) { - Symbol descriptor = types.findDescriptorSymbol(clazztype.tsym); - int count = 0; - boolean found = false; - for (Symbol sym : csym.members().getSymbols()) { - if ((sym.flags() & SYNTHETIC) != 0 || - sym.isConstructor()) continue; - count++; - if (sym.kind != MTH || - !sym.name.equals(descriptor.name)) continue; - Type mtype = types.memberType(clazztype, sym); - if (types.overrideEquivalent(mtype, types.memberType(clazztype, descriptor))) { - found = true; - } - } - if (found && count == 1) { - log.note(tree.def, "potential.lambda.found"); - } - } - } /** Make an attributed null check tree. */ @@ -2361,6 +2305,7 @@ public class Attr extends JCTree.Visitor { preFlow(that); flow.analyzeLambda(env, that, make, isSpeculativeRound); + that.type = currentTarget; //avoids recovery at this stage checkLambdaCompatible(that, lambdaType, resultInfo.checkContext); if (!isSpeculativeRound) { @@ -2801,7 +2746,7 @@ public class Attr extends JCTree.Visitor { that.kind.isUnbound() ? argtypes.tail : argtypes, typeargtypes), new FunctionalReturnContext(resultInfo.checkContext)); - Type refType = checkId(that, lookupHelper.site, refSym, localEnv, checkInfo); + Type refType = checkId(noCheckTree, lookupHelper.site, refSym, localEnv, checkInfo); if (that.kind.isUnbound() && resultInfo.checkContext.inferenceContext().free(argtypes.head)) { @@ -2823,6 +2768,8 @@ public class Attr extends JCTree.Visitor { //is a no-op (as this has been taken care during method applicability) boolean isSpeculativeRound = resultInfo.checkContext.deferredAttrContext().mode == DeferredAttr.AttrMode.SPECULATIVE; + + that.type = currentTarget; //avoids recovery at this stage checkReferenceCompatible(that, desc, refType, resultInfo.checkContext, isSpeculativeRound); if (!isSpeculativeRound) { checkAccessibleTypes(that, localEnv, resultInfo.checkContext.inferenceContext(), desc, currentTarget); @@ -3953,7 +3900,7 @@ public class Attr extends JCTree.Visitor { all_multicatchTypes.append(ctype); } } - Type t = check(tree, types.lub(multicatchTypes.toList()), + Type t = check(noCheckTree, types.lub(multicatchTypes.toList()), KindSelector.TYP, resultInfo); if (t.hasTag(CLASS)) { List alternatives = diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/AttrContext.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/AttrContext.java index b79807f10e7..db812ff0687 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/AttrContext.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/AttrContext.java @@ -59,6 +59,10 @@ public class AttrContext { */ boolean isSerializable = false; + /** Is this a speculative attribution environment? + */ + boolean isSpeculative = false; + /** Are arguments to current function applications boxed into an array for varargs? */ Resolve.MethodResolutionPhase pendingResolutionPhase = null; @@ -95,6 +99,7 @@ public class AttrContext { info.returnResult = returnResult; info.defaultSuperCallSite = defaultSuperCallSite; info.isSerializable = isSerializable; + info.isSpeculative = isSpeculative; return info; } diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/DeferredAttr.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/DeferredAttr.java index 64bd9ce7696..7b7bb8c68b5 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/DeferredAttr.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/DeferredAttr.java @@ -37,15 +37,18 @@ import com.sun.tools.javac.comp.Attr.ResultInfo; import com.sun.tools.javac.comp.Infer.InferenceContext; import com.sun.tools.javac.comp.Resolve.MethodResolutionPhase; import com.sun.tools.javac.tree.JCTree.*; +import com.sun.tools.javac.util.Log.DeferredDiagnosticHandler; import java.util.ArrayList; import java.util.Collections; +import java.util.EnumMap; import java.util.EnumSet; import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.Map; import java.util.Set; import java.util.WeakHashMap; +import java.util.function.Function; import static com.sun.tools.javac.code.TypeTag.*; import static com.sun.tools.javac.tree.JCTree.Tag.*; @@ -364,28 +367,16 @@ public class DeferredAttr extends JCTree.Visitor { * disabled during speculative type-checking. */ JCTree attribSpeculative(JCTree tree, Env env, ResultInfo resultInfo) { - final JCTree newTree = new TreeCopier<>(make).copy(tree); - Env speculativeEnv = env.dup(newTree, env.info.dup(env.info.scope.dupUnshared(env.info.scope.owner))); - Log.DeferredDiagnosticHandler deferredDiagnosticHandler = - new Log.DeferredDiagnosticHandler(log, new Filter() { - public boolean accepts(final JCDiagnostic d) { - class PosScanner extends TreeScanner { - boolean found = false; + return attribSpeculative(tree, env, resultInfo, new TreeCopier<>(make), + (newTree)->new DeferredAttrDiagHandler(log, newTree)); + } - @Override - public void scan(JCTree tree) { - if (tree != null && - tree.pos() == d.getDiagnosticPosition()) { - found = true; - } - super.scan(tree); - } - } - PosScanner posScanner = new PosScanner(); - posScanner.scan(newTree); - return posScanner.found; - } - }); + JCTree attribSpeculative(JCTree tree, Env env, ResultInfo resultInfo, TreeCopier deferredCopier, + Function diagHandlerCreator) { + final JCTree newTree = deferredCopier.copy(tree); + Env speculativeEnv = env.dup(newTree, env.info.dup(env.info.scope.dupUnshared(env.info.scope.owner))); + speculativeEnv.info.isSpeculative = true; + Log.DeferredDiagnosticHandler deferredDiagnosticHandler = diagHandlerCreator.apply(newTree); try { attr.attribTree(newTree, speculativeEnv, resultInfo); unenterScanner.scan(newTree); @@ -413,6 +404,37 @@ public class DeferredAttr extends JCTree.Visitor { } } + static class DeferredAttrDiagHandler extends Log.DeferredDiagnosticHandler { + + static class PosScanner extends TreeScanner { + DiagnosticPosition pos; + boolean found = false; + + PosScanner(DiagnosticPosition pos) { + this.pos = pos; + } + + @Override + public void scan(JCTree tree) { + if (tree != null && + tree.pos() == pos) { + found = true; + } + super.scan(tree); + } + } + + DeferredAttrDiagHandler(Log log, JCTree newTree) { + super(log, new Filter() { + public boolean accepts(JCDiagnostic d) { + PosScanner posScanner = new PosScanner(d.getDiagnosticPosition()); + posScanner.scan(newTree); + return posScanner.found; + } + }); + } + } + /** * A deferred context is created on each method check. A deferred context is * used to keep track of information associated with the method check, such as @@ -817,6 +839,14 @@ public class DeferredAttr extends JCTree.Visitor { /** an empty deferred attribution context - all methods throw exceptions */ final DeferredAttrContext emptyDeferredAttrContext; + /** The AttrMode to descriptive name mapping */ + private static final EnumMap deferredTypeMapDescriptions; + static { + deferredTypeMapDescriptions = new EnumMap<>(AttrMode.class); + deferredTypeMapDescriptions.put(AttrMode.CHECK, "deferredTypeMap[CHECK]"); + deferredTypeMapDescriptions.put(AttrMode.SPECULATIVE, "deferredTypeMap[SPECULATIVE]"); + } + /** * Map a list of types possibly containing one or more deferred types * into a list of ordinary types. Each deferred type D is mapped into a type T, @@ -824,11 +854,10 @@ public class DeferredAttr extends JCTree.Visitor { * computed for D during a previous deferred attribution round of the given kind. */ class DeferredTypeMap extends Type.Mapping { - DeferredAttrContext deferredAttrContext; protected DeferredTypeMap(AttrMode mode, Symbol msym, MethodResolutionPhase phase) { - super(String.format("deferredTypeMap[%s]", mode)); + super(deferredTypeMapDescriptions.get(mode)); this.deferredAttrContext = new DeferredAttrContext(mode, msym, phase, infer.emptyContext, emptyDeferredAttrContext, types.noWarnings); } @@ -1221,7 +1250,7 @@ public class DeferredAttr extends JCTree.Visitor { @Override public void visitNewClass(JCNewClass tree) { - result = (TreeInfo.isDiamond(tree) || attr.findDiamonds) ? + result = TreeInfo.isDiamond(tree) ? ArgumentExpressionKind.POLY : ArgumentExpressionKind.NO_POLY; } diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java index df06e137a9e..840f48e6335 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java @@ -1176,12 +1176,14 @@ public class LambdaToMethod extends TreeTranslator { @Override public void visitClassDef(JCClassDecl tree) { List prevStack = frameStack; + int prevLambdaCount = lambdaCount; SyntheticMethodNameCounter prevSyntheticMethodNameCounts = syntheticMethodNameCounts; Map prevClinits = clinits; DiagnosticSource prevSource = log.currentSource(); try { log.useSource(tree.sym.sourcefile); + lambdaCount = 0; syntheticMethodNameCounts = new SyntheticMethodNameCounter(); prevClinits = new HashMap<>(); if (tree.sym.owner.kind == MTH) { @@ -1208,6 +1210,7 @@ public class LambdaToMethod extends TreeTranslator { finally { log.useSource(prevSource.getFile()); frameStack = prevStack; + lambdaCount = prevLambdaCount; syntheticMethodNameCounts = prevSyntheticMethodNameCounts; clinits = prevClinits; } diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java index be15a750dd9..c9f2e2d9c01 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java @@ -251,19 +251,19 @@ public class JavacParser implements Parser { * mode = NOPARAMS : no parameters allowed for type * mode = TYPEARG : type argument */ - static final int EXPR = 0x1; - static final int TYPE = 0x2; - static final int NOPARAMS = 0x4; - static final int TYPEARG = 0x8; - static final int DIAMOND = 0x10; + protected static final int EXPR = 0x1; + protected static final int TYPE = 0x2; + protected static final int NOPARAMS = 0x4; + protected static final int TYPEARG = 0x8; + protected static final int DIAMOND = 0x10; /** The current mode. */ - private int mode = 0; + protected int mode = 0; /** The mode of the term that was parsed last. */ - private int lastmode = 0; + protected int lastmode = 0; /* ---------- token management -------------- */ @@ -326,7 +326,7 @@ public class JavacParser implements Parser { /** Skip forward until a suitable stop token is found. */ - private void skip(boolean stopAtImport, boolean stopAtMemberDecl, boolean stopAtIdentifier, boolean stopAtStatement) { + protected void skip(boolean stopAtImport, boolean stopAtMemberDecl, boolean stopAtIdentifier, boolean stopAtStatement) { while (true) { switch (token.kind) { case SEMI: @@ -403,11 +403,11 @@ public class JavacParser implements Parser { } } - private JCErroneous syntaxError(int pos, String key, TokenKind... args) { + protected JCErroneous syntaxError(int pos, String key, TokenKind... args) { return syntaxError(pos, List.nil(), key, args); } - private JCErroneous syntaxError(int pos, List errs, String key, TokenKind... args) { + protected JCErroneous syntaxError(int pos, List errs, String key, TokenKind... args) { setErrorEndPos(pos); JCErroneous err = F.at(pos).Erroneous(errs); reportSyntaxError(err, key, (Object[])args); @@ -427,7 +427,7 @@ public class JavacParser implements Parser { * Report a syntax using the given the position parameter and arguments, * unless one was already reported at the same position. */ - private void reportSyntaxError(int pos, String key, Object... args) { + protected void reportSyntaxError(int pos, String key, Object... args) { JCDiagnostic.DiagnosticPosition diag = new JCDiagnostic.SimpleDiagnosticPosition(pos); reportSyntaxError(diag, key, args); } @@ -436,7 +436,7 @@ public class JavacParser implements Parser { * Report a syntax error using the given DiagnosticPosition object and * arguments, unless one was already reported at the same position. */ - private void reportSyntaxError(JCDiagnostic.DiagnosticPosition diagPos, String key, Object... args) { + protected void reportSyntaxError(JCDiagnostic.DiagnosticPosition diagPos, String key, Object... args) { int pos = diagPos.getPreferredPosition(); if (pos > S.errPos() || pos == Position.NOPOS) { if (token.kind == EOF) { @@ -459,14 +459,14 @@ public class JavacParser implements Parser { /** Generate a syntax error at current position unless one was already * reported at the same position. */ - private JCErroneous syntaxError(String key) { + protected JCErroneous syntaxError(String key) { return syntaxError(token.pos, key); } /** Generate a syntax error at current position unless one was * already reported at the same position. */ - private JCErroneous syntaxError(String key, TokenKind arg) { + protected JCErroneous syntaxError(String key, TokenKind arg) { return syntaxError(token.pos, key, arg); } @@ -500,7 +500,7 @@ public class JavacParser implements Parser { } /** Diagnose a modifier flag from the set, if any. */ - void checkNoMods(long mods) { + protected void checkNoMods(long mods) { if (mods != 0) { long lowestMod = mods & -mods; error(token.pos, "mod.not.allowed.here", @@ -521,7 +521,7 @@ public class JavacParser implements Parser { * @param tree The tree to be used as index in the hashtable * @param dc The doc comment to associate with the tree, or null. */ - void attach(JCTree tree, Comment dc) { + protected void attach(JCTree tree, Comment dc) { if (keepDocComments && dc != null) { // System.out.println("doc comment = ");System.out.println(dc);//DEBUG docComments.putComment(tree, dc); @@ -530,19 +530,19 @@ public class JavacParser implements Parser { /* -------- source positions ------- */ - private void setErrorEndPos(int errPos) { + protected void setErrorEndPos(int errPos) { endPosTable.setErrorEndPos(errPos); } - private void storeEnd(JCTree tree, int endpos) { + protected void storeEnd(JCTree tree, int endpos) { endPosTable.storeEnd(tree, endpos); } - private T to(T t) { + protected T to(T t) { return endPosTable.to(t); } - private T toP(T t) { + protected T toP(T t) { return endPosTable.toP(t); } @@ -574,7 +574,7 @@ public class JavacParser implements Parser { /** * Ident = IDENTIFIER */ - Name ident() { + protected Name ident() { if (token.kind == IDENTIFIER) { Name name = token.name(); nextToken(); @@ -789,7 +789,7 @@ public class JavacParser implements Parser { return term(TYPE); } - JCExpression term(int newmode) { + protected JCExpression term(int newmode) { int prevmode = mode; mode = newmode; JCExpression t = term(); @@ -1669,7 +1669,7 @@ public class JavacParser implements Parser { } /** Accepts all identifier-like tokens */ - Filter LAX_IDENTIFIER = new Filter() { + protected Filter LAX_IDENTIFIER = new Filter() { public boolean accepts(TokenKind t) { return t == IDENTIFIER || t == UNDERSCORE || t == ASSERT || t == ENUM; } @@ -2408,7 +2408,7 @@ public class JavacParser implements Parser { * | ASSERT Expression [ ":" Expression ] ";" * | ";" */ - JCStatement parseSimpleStatement() { + public JCStatement parseSimpleStatement() { int pos = token.pos; switch (token.kind) { case LBRACE: @@ -2706,7 +2706,7 @@ public class JavacParser implements Parser { * * @param kind Whether to parse an ANNOTATION or TYPE_ANNOTATION */ - List annotationsOpt(Tag kind) { + protected List annotationsOpt(Tag kind) { if (token.kind != MONKEYS_AT) return List.nil(); // optimization ListBuffer buf = new ListBuffer<>(); int prevmode = mode; @@ -2732,7 +2732,7 @@ public class JavacParser implements Parser { * | NATIVE | SYNCHRONIZED | TRANSIENT | VOLATILE | "@" * | "@" Annotation */ - JCModifiers modifiersOpt() { + protected JCModifiers modifiersOpt() { return modifiersOpt(null); } protected JCModifiers modifiersOpt(JCModifiers partial) { @@ -2914,7 +2914,7 @@ public class JavacParser implements Parser { * @param reqInit Is an initializer always required? * @param dc The documentation comment for the variable declarations, or null. */ - > T variableDeclaratorsRest(int pos, + protected > T variableDeclaratorsRest(int pos, JCModifiers mods, JCExpression type, Name name, @@ -3117,7 +3117,7 @@ public class JavacParser implements Parser { /** ImportDeclaration = IMPORT [ STATIC ] Ident { "." Ident } [ "." "*" ] ";" */ - JCTree importDeclaration() { + protected JCTree importDeclaration() { int pos = token.pos; nextToken(); boolean importStatic = false; @@ -3159,7 +3159,7 @@ public class JavacParser implements Parser { * @param mods Any modifiers starting the class or interface declaration * @param dc The documentation comment for the class, or null. */ - JCStatement classOrInterfaceOrEnumDeclaration(JCModifiers mods, Comment dc) { + protected JCStatement classOrInterfaceOrEnumDeclaration(JCModifiers mods, Comment dc) { if (token.kind == CLASS) { return classDeclaration(mods, dc); } else if (token.kind == INTERFACE) { @@ -3569,7 +3569,7 @@ public class JavacParser implements Parser { * TypeParametersOpt = ["<" TypeParameter {"," TypeParameter} ">"] * } */ - List typeParametersOpt() { + protected List typeParametersOpt() { if (token.kind == LT) { ListBuffer typarams = new ListBuffer<>(); nextToken(); @@ -4004,7 +4004,7 @@ public class JavacParser implements Parser { allowTypeAnnotations = true; } } - void checkAnnotationsAfterTypeParams(int pos) { + protected void checkAnnotationsAfterTypeParams(int pos) { if (!allowAnnotationsAfterTypeParams) { log.error(pos, "annotations.after.type.params.not.supported.in.source", source.name); allowAnnotationsAfterTypeParams = true; @@ -4092,7 +4092,7 @@ public class JavacParser implements Parser { /** * Store the last error position. */ - protected int errorEndPos = Position.NOPOS; + public int errorEndPos = Position.NOPOS; public AbstractEndPosTable(JavacParser parser) { this.parser = parser; @@ -4119,13 +4119,13 @@ public class JavacParser implements Parser { * will be set only if it is greater than the last stored error position. * @param errPos The error position */ - protected void setErrorEndPos(int errPos) { + public void setErrorEndPos(int errPos) { if (errPos > errorEndPos) { errorEndPos = errPos; } } - protected void setParser(JavacParser parser) { + public void setParser(JavacParser parser) { this.parser = parser; } } diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties index b22e6970567..89eeadaeaad 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties @@ -1196,9 +1196,6 @@ compiler.warn.file.from.future=\ compiler.note.compressed.diags=\ Some messages have been simplified; recompile with -Xdiags:verbose to get full output -compiler.note.potential.lambda.found=\ - This anonymous inner class creation can be turned into a lambda expression. - # 0: boolean, 1: symbol compiler.note.lambda.stat=\ Translating lambda expression\n\ @@ -1640,14 +1637,20 @@ compiler.warn.raw.class.use=\ # 0: unused, 1: unused compiler.warn.diamond.redundant.args=\ - redundant type arguments in new expression (use diamond operator instead). + Redundant type arguments in new expression (use diamond operator instead). -# 0: type, 1: type +# 0: type, 1: list of type compiler.warn.diamond.redundant.args.1=\ - redundant type arguments in new expression (use diamond operator instead).\n\ + Redundant type arguments in new expression (use diamond operator instead).\n\ explicit: {0}\n\ inferred: {1} +compiler.warn.potential.lambda.found=\ + This anonymous inner class creation can be turned into a lambda expression. + +compiler.warn.method.redundant.typeargs=\ + Redundant type arguments in method call. + # 0: symbol, 1: message segment compiler.warn.varargs.redundant.trustme.anno=\ Redundant {0} annotation. {1} diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeInfo.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeInfo.java index 184c673eb0d..64dc16ada0c 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeInfo.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeInfo.java @@ -313,6 +313,14 @@ public class TreeInfo { } } + /** Return true if the tree corresponds to a statement */ + public static boolean isStatement(JCTree tree) { + return (tree instanceof JCStatement) && + !tree.hasTag(CLASSDEF) && + !tree.hasTag(Tag.BLOCK) && + !tree.hasTag(METHODDEF); + } + /** * Return true if the AST corresponds to a static select of the kind A.B */ diff --git a/langtools/src/jdk.dev/share/classes/com/sun/tools/jdeps/JdepsTask.java b/langtools/src/jdk.dev/share/classes/com/sun/tools/jdeps/JdepsTask.java index 3a93327d5e4..a430df9b2ae 100644 --- a/langtools/src/jdk.dev/share/classes/com/sun/tools/jdeps/JdepsTask.java +++ b/langtools/src/jdk.dev/share/classes/com/sun/tools/jdeps/JdepsTask.java @@ -554,8 +554,9 @@ class JdepsTask { classpaths.addAll(PlatformClassPath.getModules(options.mpath)); if (options.mpath != null) { initialArchives.addAll(PlatformClassPath.getModules(options.mpath)); + } else { + classpaths.addAll(PlatformClassPath.getJarFiles()); } - classpaths.addAll(PlatformClassPath.getJarFiles()); // add all classpath archives to the source locations for reporting sourceLocations.addAll(classpaths); } diff --git a/langtools/test/Makefile b/langtools/test/Makefile index 08d4fc48882..c2151108101 100644 --- a/langtools/test/Makefile +++ b/langtools/test/Makefile @@ -21,7 +21,6 @@ OSNAME = $(shell uname -s) ifeq ($(OSNAME), SunOS) SLASH_JAVA = /java PLATFORM = solaris - JT_PLATFORM = solaris ARCH = $(shell uname -p) ifeq ($(ARCH), i386) ARCH=i586 @@ -30,7 +29,6 @@ endif ifeq ($(OSNAME), Linux) SLASH_JAVA = /java PLATFORM = linux - JT_PLATFORM = linux ARCH = $(shell uname -m) ifeq ($(ARCH), i386) ARCH=i586 @@ -38,7 +36,6 @@ ifeq ($(OSNAME), Linux) endif ifeq ($(OSNAME), Darwin) PLATFORM = bsd - JT_PLATFORM = linux ARCH = $(shell uname -m) ifeq ($(ARCH), i386) ARCH=i586 @@ -55,7 +52,6 @@ endif ifeq ($(PLATFORM), windows) SLASH_JAVA = J: - JT_PLATFORM = win32 ifeq ($(word 1, $(PROCESSOR_IDENTIFIER)),ia64) ARCH=ia64 else @@ -93,8 +89,8 @@ ifdef JPRT_JTREG_HOME else JTREG_HOME = $(SLASH_JAVA)/re/jtreg/4.1/promoted/latest/binaries/jtreg endif -JTREG = $(JTREG_HOME)/$(JT_PLATFORM)/bin/jtreg -JTDIFF = $(JTREG_HOME)/$(JT_PLATFORM)/bin/jtdiff +JTREG = $(JTREG_HOME)/bin/jtreg +JTDIFF = $(JTREG_HOME)/bin/jtdiff # Default JCK to run ifdef JPRT_JCK_HOME @@ -105,21 +101,19 @@ endif # Default JDK for JTREG and JCK # -# JT_JAVA is the version of java used to run jtreg/JCK. Since it is now -# standard to execute tests in sameVM mode, it should normally be set the -# same as TESTJAVA (although not necessarily so.) +# JT_JAVA is the version of java used to run jtreg/JCK. # ifdef JPRT_JAVA_HOME JT_JAVA = $(JPRT_JAVA_HOME) else - JT_JAVA = $(SLASH_JAVA)/re/jdk/1.7.0/archive/fcs/binaries/$(PLATFORM)-$(ARCH) + JT_JAVA = $(SLASH_JAVA)/re/jdk/1.9.0/archive/fcs/binaries/$(PLATFORM)-$(ARCH) endif # Default JDK to test ifdef JPRT_IMPORT_PRODUCT_HOME TESTJAVA = $(JPRT_IMPORT_PRODUCT_HOME) else - TESTJAVA = $(SLASH_JAVA)/re/jdk/1.7.0/promoted/latest/binaries/$(PLATFORM)-$(ARCH) + TESTJAVA = $(SLASH_JAVA)/re/jdk/1.9.0/promoted/latest/binaries/$(PLATFORM)-$(ARCH) endif # PRODUCT_HOME is a JPRT variable pointing to a directory containing the output from @@ -152,7 +146,7 @@ endif ifdef CONCURRENCY JTREG_OPTIONS += -agentvm -concurrency:$(CONCURRENCY) else - JTREG_OPTIONS += -samevm + JTREG_OPTIONS += -agentvm endif ifdef JCK_CONCURRENCY diff --git a/langtools/test/tools/javac/diags/examples/DiamondRedundantArgs.java b/langtools/test/tools/javac/diags/examples/DiamondRedundantArgs.java index d8502c319ce..662a082575c 100644 --- a/langtools/test/tools/javac/diags/examples/DiamondRedundantArgs.java +++ b/langtools/test/tools/javac/diags/examples/DiamondRedundantArgs.java @@ -22,8 +22,8 @@ */ // key: compiler.warn.diamond.redundant.args -// options: -XDfindDiamond +// options: -XDfind=diamond -class Foo { - Foo fs = new Foo(); +class DiamondRedundantArgs { + DiamondRedundantArgs fs = new DiamondRedundantArgs(); } diff --git a/langtools/test/tools/javac/diags/examples/DiamondRedundantArgs1.java b/langtools/test/tools/javac/diags/examples/DiamondRedundantArgs1.java index ddc8502f92f..8fd781daaef 100644 --- a/langtools/test/tools/javac/diags/examples/DiamondRedundantArgs1.java +++ b/langtools/test/tools/javac/diags/examples/DiamondRedundantArgs1.java @@ -22,8 +22,8 @@ */ // key: compiler.warn.diamond.redundant.args.1 -// options: -XDfindDiamond +// options: -XDfind=diamond -class Foo { - Foo fs = new Foo(); +class DiamondRedundantArgs1 { + DiamondRedundantArgs1 fs = new DiamondRedundantArgs1(); } diff --git a/langtools/test/tools/javac/diags/examples/MethodRedundantTypeargs.java b/langtools/test/tools/javac/diags/examples/MethodRedundantTypeargs.java new file mode 100644 index 00000000000..373be444214 --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/MethodRedundantTypeargs.java @@ -0,0 +1,35 @@ +/* + * 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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. + */ + +// key: compiler.warn.method.redundant.typeargs +// options: -XDfind=method + +class MethodRedundantTypeargs { + Z id(Z z) { return z; } + + void test() { + String s = this.id(""); + } +} diff --git a/langtools/test/tools/javac/diags/examples/PotentialLambdaFound.java b/langtools/test/tools/javac/diags/examples/PotentialLambdaFound.java index 050f26c4eae..99cacac8795 100644 --- a/langtools/test/tools/javac/diags/examples/PotentialLambdaFound.java +++ b/langtools/test/tools/javac/diags/examples/PotentialLambdaFound.java @@ -21,8 +21,8 @@ * questions. */ -// key: compiler.note.potential.lambda.found -// options: -XDidentifyLambdaCandidate=true +// key: compiler.warn.potential.lambda.found +// options: -XDfind=lambda class PotentialLambdaFound { diff --git a/langtools/test/tools/javac/generics/diamond/6939780/T6939780.java b/langtools/test/tools/javac/generics/diamond/6939780/T6939780.java index d3f41e44fb7..6d7ef0da676 100644 --- a/langtools/test/tools/javac/generics/diamond/6939780/T6939780.java +++ b/langtools/test/tools/javac/generics/diamond/6939780/T6939780.java @@ -1,11 +1,11 @@ /* * @test /nodynamiccopyright/ - * @bug 6939780 7020044 8009459 8021338 + * @bug 6939780 7020044 8009459 8021338 8064365 * * @summary add a warning to detect diamond sites * @author mcimadamore - * @compile/ref=T6939780_7.out -Xlint:-options -source 7 T6939780.java -XDrawDiagnostics -XDfindDiamond - * @compile/ref=T6939780_8.out T6939780.java -XDrawDiagnostics -XDfindDiamond + * @compile/ref=T6939780_7.out -Xlint:-options -source 7 T6939780.java -XDrawDiagnostics -XDfind=diamond + * @compile/ref=T6939780_8.out T6939780.java -XDrawDiagnostics -XDfind=diamond * */ diff --git a/langtools/test/tools/javac/generics/diamond/6939780/T6939780_7.out b/langtools/test/tools/javac/generics/diamond/6939780/T6939780_7.out index f44ff80ba2e..52d621d78df 100644 --- a/langtools/test/tools/javac/generics/diamond/6939780/T6939780_7.out +++ b/langtools/test/tools/javac/generics/diamond/6939780/T6939780_7.out @@ -1,4 +1,5 @@ -T6939780.java:21:28: compiler.warn.diamond.redundant.args: T6939780.Foo, T6939780.Foo +T6939780.java:21:28: compiler.warn.diamond.redundant.args T6939780.java:22:28: compiler.warn.diamond.redundant.args.1: T6939780.Foo, T6939780.Foo -T6939780.java:30:19: compiler.warn.diamond.redundant.args: T6939780.Foo, T6939780.Foo -3 warnings +T6939780.java:30:19: compiler.warn.diamond.redundant.args +T6939780.java:31:19: compiler.warn.diamond.redundant.args.1: T6939780.Foo, T6939780.Foo +4 warnings diff --git a/langtools/test/tools/javac/generics/diamond/6939780/T6939780_8.out b/langtools/test/tools/javac/generics/diamond/6939780/T6939780_8.out index dfbda806230..3d979d15147 100644 --- a/langtools/test/tools/javac/generics/diamond/6939780/T6939780_8.out +++ b/langtools/test/tools/javac/generics/diamond/6939780/T6939780_8.out @@ -1,7 +1,7 @@ -T6939780.java:20:33: compiler.warn.diamond.redundant.args: T6939780.Foo, T6939780.Foo -T6939780.java:21:28: compiler.warn.diamond.redundant.args: T6939780.Foo, T6939780.Foo +T6939780.java:20:33: compiler.warn.diamond.redundant.args +T6939780.java:21:28: compiler.warn.diamond.redundant.args T6939780.java:22:28: compiler.warn.diamond.redundant.args.1: T6939780.Foo, T6939780.Foo -T6939780.java:29:19: compiler.warn.diamond.redundant.args: T6939780.Foo, T6939780.Foo -T6939780.java:30:19: compiler.warn.diamond.redundant.args: T6939780.Foo, T6939780.Foo +T6939780.java:29:19: compiler.warn.diamond.redundant.args +T6939780.java:30:19: compiler.warn.diamond.redundant.args T6939780.java:31:19: compiler.warn.diamond.redundant.args.1: T6939780.Foo, T6939780.Foo 6 warnings diff --git a/langtools/test/tools/javac/generics/diamond/7002837/T7002837.java b/langtools/test/tools/javac/generics/diamond/7002837/T7002837.java index acdb72bb02e..d5ff88dd858 100644 --- a/langtools/test/tools/javac/generics/diamond/7002837/T7002837.java +++ b/langtools/test/tools/javac/generics/diamond/7002837/T7002837.java @@ -1,10 +1,10 @@ /* * @test /nodynamiccopyright/ - * @bug 7002837 + * @bug 7002837 8064365 * * @summary Diamond: javac generates diamond inference errors when in 'finder' mode * @author mcimadamore - * @compile/fail/ref=T7002837.out -Werror -XDrawDiagnostics -XDfindDiamond T7002837.java + * @compile/fail/ref=T7002837.out -Werror -XDrawDiagnostics -XDfind=diamond T7002837.java * */ diff --git a/langtools/test/tools/javac/lambda/8066974/T8066974.java b/langtools/test/tools/javac/lambda/8066974/T8066974.java new file mode 100644 index 00000000000..8f47277f734 --- /dev/null +++ b/langtools/test/tools/javac/lambda/8066974/T8066974.java @@ -0,0 +1,44 @@ +/* + * @test /nodynamiccopyright/ + * @bug 8066974 + * @summary Compiler doesn't infer method's generic type information in lambda body + * @compile/fail/ref=T8066974.out -XDrawDiagnostics T8066974.java + */ +class T8066974 { + static class Throwing { } + static class RuntimeThrowing extends Throwing { } + static class CheckedThrowing extends Throwing { } + + interface Parameter { + Object m(Throwing tw) throws E; + } + + interface Mapper { + R m(Parameter p); + } + + Z map(Mapper mz) { return null; } + + Mapper> mapper(Throwing tz) throws Z { return null; } + + static class ThrowingMapper implements Mapper> { + ThrowingMapper(Throwing arg) throws X { } + + @Override + public Throwing m(Parameter p) { + return null; + } + } + + void testRuntime(RuntimeThrowing rt) { + map(p->p.m(rt)); + map(mapper(rt)); + map(new ThrowingMapper<>(rt)); + } + + void testChecked(CheckedThrowing ct) { + map(p->p.m(ct)); + map(mapper(ct)); + map(new ThrowingMapper<>(ct)); + } +} diff --git a/langtools/test/tools/javac/lambda/8066974/T8066974.out b/langtools/test/tools/javac/lambda/8066974/T8066974.out new file mode 100644 index 00000000000..59772fc59a4 --- /dev/null +++ b/langtools/test/tools/javac/lambda/8066974/T8066974.out @@ -0,0 +1,4 @@ +T8066974.java:40:19: compiler.err.unreported.exception.need.to.catch.or.throw: java.lang.Exception +T8066974.java:41:19: compiler.err.unreported.exception.need.to.catch.or.throw: java.lang.Exception +T8066974.java:42:13: compiler.err.unreported.exception.need.to.catch.or.throw: java.lang.Exception +3 errors diff --git a/langtools/test/tools/javac/lambda/8067792/T8067792.java b/langtools/test/tools/javac/lambda/8067792/T8067792.java new file mode 100644 index 00000000000..a050171991e --- /dev/null +++ b/langtools/test/tools/javac/lambda/8067792/T8067792.java @@ -0,0 +1,19 @@ +/* + * @test /nodynamiccopyright/ + * @bug 8067792 + * @summary Javac crashes in finder mode with nested implicit lambdas + * @compile/fail/ref=T8067792.out -XDrawDiagnostics -Werror -XDfind=lambda T8067792.java + */ + +import java.util.stream.*; +import java.util.*; + +class T8067792 { + void test(Stream> sl) { + Runnable r = new Runnable() { + public void run() { + Stream> constructor = sl.filter(c -> true); + } + }; + } +} diff --git a/langtools/test/tools/javac/lambda/8067792/T8067792.out b/langtools/test/tools/javac/lambda/8067792/T8067792.out new file mode 100644 index 00000000000..718d1539d74 --- /dev/null +++ b/langtools/test/tools/javac/lambda/8067792/T8067792.out @@ -0,0 +1,4 @@ +T8067792.java:13:37: compiler.warn.potential.lambda.found +- compiler.err.warnings.and.werror +1 error +1 warning diff --git a/langtools/test/tools/javac/lambda/LambdaConv18.java b/langtools/test/tools/javac/lambda/LambdaConv18.java index 279d99ff17c..3a8efb206fc 100644 --- a/langtools/test/tools/javac/lambda/LambdaConv18.java +++ b/langtools/test/tools/javac/lambda/LambdaConv18.java @@ -1,9 +1,9 @@ /* * @test /nodynamiccopyright/ - * @bug 8003280 + * @bug 8003280 8064365 * @summary Add lambda tests * simple test for lambda candidate check - * @compile/fail/ref=LambdaConv18.out -XDrawDiagnostics -XDidentifyLambdaCandidate=true LambdaConv18.java + * @compile/fail/ref=LambdaConv18.out -XDrawDiagnostics -XDfind=lambda LambdaConv18.java */ class LambdaConv18 { diff --git a/langtools/test/tools/javac/lambda/LambdaConv18.out b/langtools/test/tools/javac/lambda/LambdaConv18.out index fa84e6b43f3..2213718ab3c 100644 --- a/langtools/test/tools/javac/lambda/LambdaConv18.out +++ b/langtools/test/tools/javac/lambda/LambdaConv18.out @@ -1,4 +1,5 @@ LambdaConv18.java:23:5: compiler.err.cant.resolve.location: kindname.class, NonExistent, , , (compiler.misc.location: kindname.class, LambdaConv18, null) -LambdaConv18.java:20:24: compiler.note.potential.lambda.found +LambdaConv18.java:20:24: compiler.warn.potential.lambda.found LambdaConv18.java:23:26: compiler.err.cant.resolve.location: kindname.class, NonExistent, , , (compiler.misc.location: kindname.class, LambdaConv18, null) 2 errors +1 warning diff --git a/langtools/test/tools/javac/lambda/lambdaNaming/TestNonSerializableLambdaNameStability.java b/langtools/test/tools/javac/lambda/lambdaNaming/TestNonSerializableLambdaNameStability.java new file mode 100644 index 00000000000..40380bd55e8 --- /dev/null +++ b/langtools/test/tools/javac/lambda/lambdaNaming/TestNonSerializableLambdaNameStability.java @@ -0,0 +1,100 @@ +/* + * 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 8067422 + * @summary Check that the lambda names are not unnecessarily unstable + * @library /tools/lib + * @build ToolBox + * @run main TestNonSerializableLambdaNameStability + */ + +import com.sun.tools.classfile.ClassFile; +import com.sun.tools.classfile.Method; +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; +import javax.tools.StandardLocation; + +public class TestNonSerializableLambdaNameStability { + + public static void main(String... args) throws Exception { + new TestNonSerializableLambdaNameStability().run(); + } + + String lambdaSource = "public class L%d {\n" + + " public static class A {\n" + + " private Runnable r = () -> { };\n" + + " }\n" + + " public static class B {\n" + + " private Runnable r = () -> { };\n" + + " }\n" + + " private Runnable r = () -> { };\n" + + "}\n"; + + String expectedLambdaMethodName = "lambda$new$0"; + + void run() throws Exception { + List sources = new ArrayList<>(); + + for (int i = 0; i < 3; i++) { + sources.add(String.format(lambdaSource, i)); + } + + ToolBox tb = new ToolBox(); + + try (ToolBox.MemoryFileManager fm = new ToolBox.MemoryFileManager()) { + tb.new JavacTask() + .sources(sources.toArray(new String[sources.size()])) + .fileManager(fm) + .run(); + + for (String file : fm.files.get(StandardLocation.CLASS_OUTPUT).keySet()) { + byte[] fileBytes = fm.getFileBytes(StandardLocation.CLASS_OUTPUT, file); + try (InputStream in = new ByteArrayInputStream(fileBytes)) { + boolean foundLambdaMethod = false; + ClassFile cf = ClassFile.read(in); + StringBuilder seenMethods = new StringBuilder(); + String sep = ""; + for (Method m : cf.methods) { + String methodName = m.getName(cf.constant_pool); + if (expectedLambdaMethodName.equals(methodName)) { + foundLambdaMethod = true; + break; + } + seenMethods.append(sep); + seenMethods.append(methodName); + sep = ", "; + } + + if (!foundLambdaMethod) { + throw new AbstractMethodError("Did not find the lambda method, " + + "found methods: " + seenMethods.toString()); + } + } + } + } + } +} diff --git a/langtools/test/tools/javac/lambda/speculative/DiamondFinder.java b/langtools/test/tools/javac/lambda/speculative/DiamondFinder.java index 35f56afaacb..38cd0266ef3 100644 --- a/langtools/test/tools/javac/lambda/speculative/DiamondFinder.java +++ b/langtools/test/tools/javac/lambda/speculative/DiamondFinder.java @@ -23,10 +23,10 @@ /* * @test - * @bug 8003280 + * @bug 8003280 8064365 * @summary Add lambda tests * spurious crashes when running in 'diamond finder' mode - * @compile -XDfindDiamond DiamondFinder.java + * @compile -XDfind=diamond DiamondFinder.java */ import java.util.*; diff --git a/langtools/test/tools/sjavac/CompileCircularSources.java b/langtools/test/tools/sjavac/CompileCircularSources.java new file mode 100644 index 00000000000..f4a916ec074 --- /dev/null +++ b/langtools/test/tools/sjavac/CompileCircularSources.java @@ -0,0 +1,70 @@ +/* + * 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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 + * @summary Verify that circular sources split on multiple cores can be compiled + * @bug 8054689 + * @author Fredrik O + * @author sogoel (rewrite) + * @library /tools/lib + * @build Wrapper ToolBox + * @run main Wrapper CompileCircularSources + */ + +import java.util.*; +import java.nio.file.*; + +public class CompileCircularSources extends SJavacTester { + public static void main(String... args) throws Exception { + CompileCircularSources ccs = new CompileCircularSources(); + ccs.test(); + } + + void test() throws Exception { + Files.createDirectory(BIN); + clean(GENSRC, BIN); + + Map previous_bin_state = collectState(BIN); + + ToolBox tb = new ToolBox(); + tb.writeFile(GENSRC.resolve("alfa/omega/A.java"), + "package alfa.omega; public class A { beta.B b; }"); + tb.writeFile(GENSRC.resolve("beta/B.java"), + "package beta; public class B { gamma.C c; }"); + tb.writeFile(GENSRC.resolve("gamma/C.java"), + "package gamma; public class C { alfa.omega.A a; }"); + + compile("gensrc", "-d", "bin", "-h", "headers", "-j", "3", + SERVER_ARG,"--log=debug"); + Map new_bin_state = collectState(BIN); + verifyThatFilesHaveBeenAdded(previous_bin_state, new_bin_state, + "bin/alfa/omega/A.class", + "bin/beta/B.class", + "bin/gamma/C.class", + "bin/javac_state"); + clean(GENSRC, BIN); + } +} diff --git a/langtools/test/tools/sjavac/CompileExcludingDependency.java b/langtools/test/tools/sjavac/CompileExcludingDependency.java new file mode 100644 index 00000000000..c59600d1d09 --- /dev/null +++ b/langtools/test/tools/sjavac/CompileExcludingDependency.java @@ -0,0 +1,66 @@ +/* + * 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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 + * @summary Tests compiling class A that depends on class B without compiling class B + * @bug 8054689 + * @author Fredrik O + * @author sogoel (rewrite) + * @library /tools/lib + * @build Wrapper ToolBox + * @run main Wrapper CompileExcludingDependency + */ + +import java.util.*; +import java.nio.file.*; + +public class CompileExcludingDependency extends SJavacTester { + public static void main(String... args) throws Exception { + CompileExcludingDependency ced = new CompileExcludingDependency(); + ced.test(); + } + + // Verify that excluding classes from compilation but not from linking works + void test() throws Exception { + Files.createDirectory(BIN); + clean(GENSRC,BIN); + Map previous_bin_state = collectState(BIN); + ToolBox tb = new ToolBox(); + tb.writeFile(GENSRC.resolve("alfa/omega/A.java"), + "package alfa.omega; public class A { beta.B b; }"); + tb.writeFile(GENSRC.resolve("beta/B.java"), + "package beta; public class B { }"); + + compile("-x", "beta", "-src", "gensrc", "-x", "alfa/omega", "-sourcepath", "gensrc", + "-d", "bin", SERVER_ARG); + + Map new_bin_state = collectState(BIN); + verifyThatFilesHaveBeenAdded(previous_bin_state, new_bin_state, + "bin/alfa/omega/A.class", + "bin/javac_state"); + clean(GENSRC, BIN); + } +} diff --git a/langtools/test/tools/sjavac/CompileWithAtFile.java b/langtools/test/tools/sjavac/CompileWithAtFile.java new file mode 100644 index 00000000000..1c710da693c --- /dev/null +++ b/langtools/test/tools/sjavac/CompileWithAtFile.java @@ -0,0 +1,68 @@ +/* + * 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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 + * @summary Test \@atfile with command line content + * @bug 8054689 + * @author Fredrik O + * @author sogoel (rewrite) + * @library /tools/lib + * @build Wrapper ToolBox + * @run main Wrapper CompileWithAtFile + */ + +import java.util.*; +import java.nio.file.*; + +public class CompileWithAtFile extends SJavacTester { + public static void main(String... args) throws Exception { + CompileWithAtFile cwf = new CompileWithAtFile(); + cwf.test(); + } + + void test() throws Exception { + ToolBox tb = new ToolBox(); + tb.writeFile(GENSRC.resolve("list.txt"), + "-if */alfa/omega/A.java\n-if */beta/B.java\ngensrc\n-d bin\n"); + tb.writeFile(GENSRC.resolve("alfa/omega/A.java"), + "package alfa.omega; import beta.B; public class A { B b; }"); + tb.writeFile(GENSRC.resolve("beta/B.java"), + "package beta; public class B { }"); + tb.writeFile(GENSRC.resolve("beta/C.java"), + "broken"); + + Files.createDirectory(BIN); + Map previous_bin_state = collectState(BIN); + compile("@gensrc/list.txt", "--server:portfile=testserver,background=false"); + + Map new_bin_state = collectState(BIN); + verifyThatFilesHaveBeenAdded(previous_bin_state, new_bin_state, + "bin/javac_state", + "bin/alfa/omega/A.class", + "bin/beta/B.class"); + clean(GENSRC, BIN); + } +} diff --git a/langtools/test/tools/sjavac/CompileWithInvisibleSources.java b/langtools/test/tools/sjavac/CompileWithInvisibleSources.java new file mode 100644 index 00000000000..d0d3340dfc6 --- /dev/null +++ b/langtools/test/tools/sjavac/CompileWithInvisibleSources.java @@ -0,0 +1,84 @@ +/* + * 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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 + * @summary Verify that we can make sources invisible to linking (sourcepath) + * @bug 8054689 + * @author Fredrik O + * @author sogoel (rewrite) + * @library /tools/lib + * @build Wrapper ToolBox + * @run main Wrapper CompileWithInvisibleSources + */ + +import java.util.*; +import java.nio.file.*; + +public class CompileWithInvisibleSources extends SJavacTester { + public static void main(String... args) throws Exception { + CompileWithInvisibleSources cis = new CompileWithInvisibleSources(); + cis.test(); + } + + // Compile gensrc and link against gensrc2 and gensrc3 + // gensrc2 contains broken code in beta.B, thus exclude that package + // gensrc3 contains a proper beta.B + void test() throws Exception { + Files.createDirectory(BIN); + clean(GENSRC, GENSRC2, GENSRC3, BIN); + + Map previous_bin_state = collectState(BIN); + + ToolBox tb = new ToolBox(); + tb.writeFile(GENSRC.resolve("alfa/omega/A.java"), + "package alfa.omega; import beta.B; import gamma.C; public class A { B b; C c; }"); + tb.writeFile(GENSRC2.resolve("beta/B.java"), + "package beta; public class B { broken"); + tb.writeFile(GENSRC2.resolve("gamma/C.java"), + "package gamma; public class C { }"); + tb.writeFile(GENSRC3.resolve("beta/B.java"), + "package beta; public class B { }"); + + compile("gensrc", "-x", "beta", "-sourcepath", "gensrc2", + "-sourcepath", "gensrc3", "-d", "bin", "-h", "headers", "-j", "1", + SERVER_ARG); + + System.out.println("The first compile went well!"); + Map new_bin_state = collectState(BIN); + verifyThatFilesHaveBeenAdded(previous_bin_state, new_bin_state, + "bin/alfa/omega/A.class", + "bin/javac_state"); + + System.out.println("----- Compile with exluded beta went well!"); + clean(BIN); + compileExpectFailure("gensrc", "-sourcepath", "gensrc2", "-sourcepath", "gensrc3", + "-d", "bin", "-h", "headers", "-j", "1", + SERVER_ARG); + + System.out.println("----- Compile without exluded beta failed, as expected! Good!"); + clean(GENSRC, BIN); + } +} diff --git a/langtools/test/tools/sjavac/CompileWithOverrideSources.java b/langtools/test/tools/sjavac/CompileWithOverrideSources.java new file mode 100644 index 00000000000..32e4629fe3c --- /dev/null +++ b/langtools/test/tools/sjavac/CompileWithOverrideSources.java @@ -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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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 + * @summary verify that we can override sources to be compiled + * @bug 8054689 + * @author Fredrik O + * @author sogoel (rewrite) + * @library /tools/lib + * @build Wrapper ToolBox + * @run main Wrapper CompileWithOverrideSources + */ + +import java.util.*; +import java.nio.file.*; + +public class CompileWithOverrideSources extends SJavacTester { + public static void main(String... args) throws Exception { + CompileWithOverrideSources cos = new CompileWithOverrideSources(); + cos.test(); + } + + // Compile gensrc and gensrc2. However do not compile broken beta.B in gensrc, + // only compile ok beta.B in gensrc2 + void test() throws Exception { + Files.createDirectory(BIN); + clean(GENSRC, GENSRC2, GENSRC3, BIN); + + Map previous_bin_state = collectState(BIN); + ToolBox tb = new ToolBox(); + tb.writeFile(GENSRC.resolve("alfa/omega/A.java"), + "package alfa.omega; import beta.B; import gamma.C; public class A { B b; C c; }"); + tb.writeFile(GENSRC.resolve("beta/B.java"), + "package beta; public class B { broken"); + tb.writeFile(GENSRC.resolve("gamma/C.java"), + "package gamma; public class C { }"); + + tb.writeFile(GENSRC2.resolve("beta/B.java"), + "package beta; public class B { }"); + + compile("-x", "beta", "gensrc", "gensrc2", "-d", "bin", "-h", "headers", "-j", "1", + SERVER_ARG); + Map new_bin_state = collectState(BIN); + verifyThatFilesHaveBeenAdded(previous_bin_state, new_bin_state, + "bin/alfa/omega/A.class", + "bin/beta/B.class", + "bin/gamma/C.class", + "bin/javac_state"); + + System.out.println("----- Compile with exluded beta went well!"); + clean(BIN); + compileExpectFailure("gensrc", "gensrc2", "-d", "bin", "-h", "headers", "-j", "1", + SERVER_ARG); + + System.out.println("----- Compile without exluded beta failed, as expected! Good!"); + clean(GENSRC, GENSRC2, BIN); + } +} diff --git a/langtools/test/tools/sjavac/IncCompileChangeNative.java b/langtools/test/tools/sjavac/IncCompileChangeNative.java new file mode 100644 index 00000000000..873b57f424b --- /dev/null +++ b/langtools/test/tools/sjavac/IncCompileChangeNative.java @@ -0,0 +1,111 @@ +/* + * 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 + * @summary Verify native files are removed when native method is removed + * @bug 8054689 + * @author Fredrik O + * @author sogoel (rewrite) + * @library /tools/lib + * @build Wrapper ToolBox + * @run main Wrapper IncCompileChangeNative + */ + +import java.util.*; +import java.nio.file.*; + +public class IncCompileChangeNative extends SJavacTester { + public static void main(String... args) throws Exception { + IncCompileChangeNative cn = new IncCompileChangeNative(); + cn.test(); + } + + // Remember the previous bin and headers state here. + Map previous_bin_state; + Map previous_headers_state; + ToolBox tb = new ToolBox(); + + void test() throws Exception { + Files.createDirectory(GENSRC); + Files.createDirectory(BIN); + Files.createDirectory(HEADERS); + + initialCompile(); + incrementalCompileDropAllNatives(); + incrementalCompileAddNative(); + + clean(GENSRC, BIN, HEADERS); + } + + // Update B.java with one less native method i.e. it has no longer any methods + // Verify that beta_B.h is removed + void incrementalCompileDropAllNatives() throws Exception { + previous_bin_state = collectState(BIN); + previous_headers_state = collectState(HEADERS); + System.out.println("\nIn incrementalCompileDropAllNatives() "); + System.out.println("Verify that beta_B.h is removed"); + tb.writeFile(GENSRC.resolve("beta/B.java"), + "package beta; import alfa.omega.A; public class B {"+ + "private int b() { return A.DEFINITION; } }"); + + compile("gensrc", "-d", "bin", "-h", "headers", "-j", "1", + SERVER_ARG, "--log=debug"); + Map new_bin_state = collectState(BIN); + verifyNewerFiles(previous_bin_state, new_bin_state, + "bin/beta/B.class", + "bin/beta/BINT.class", + "bin/javac_state"); + previous_bin_state = new_bin_state; + + Map new_headers_state = collectState(HEADERS); + verifyThatFilesHaveBeenRemoved(previous_headers_state, new_headers_state, + "headers/beta_B.h"); + previous_headers_state = new_headers_state; + } + + // Update the B.java with a final static annotated with @Native + // Verify that beta_B.h is added again + void incrementalCompileAddNative() throws Exception { + System.out.println("\nIn incrementalCompileAddNative() "); + System.out.println("Verify that beta_B.h is added again"); + tb.writeFile(GENSRC.resolve("beta/B.java"), + "package beta; import alfa.omega.A; public class B {"+ + "private int b() { return A.DEFINITION; } "+ + "@java.lang.annotation.Native final static int alfa = 42; }"); + + compile("gensrc", "-d", "bin", "-h", "headers", "-j", "1", + SERVER_ARG, "--log=debug"); + Map new_bin_state = collectState(BIN); + verifyNewerFiles(previous_bin_state, new_bin_state, + "bin/beta/B.class", + "bin/beta/BINT.class", + "bin/javac_state"); + previous_bin_state = new_bin_state; + + Map new_headers_state = collectState(HEADERS); + verifyThatFilesHaveBeenAdded(previous_headers_state, new_headers_state, + "headers/beta_B.h"); + previous_headers_state = new_headers_state; + } +} diff --git a/langtools/test/tools/sjavac/IncCompileDropClasses.java b/langtools/test/tools/sjavac/IncCompileDropClasses.java new file mode 100644 index 00000000000..c997972d5d1 --- /dev/null +++ b/langtools/test/tools/sjavac/IncCompileDropClasses.java @@ -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 + * @summary Verify deletion of a source file results in dropping of all .class files including inner classes + * @bug 8054689 + * @author Fredrik O + * @author sogoel (rewrite) + * @library /tools/lib + * @build Wrapper ToolBox + * @run main Wrapper IncCompileDropClasses + */ + +import java.util.*; +import java.nio.file.*; + +public class IncCompileDropClasses extends SJavacTester { + public static void main(String... args) throws Exception { + IncCompileDropClasses dc = new IncCompileDropClasses(); + dc.test(); + } + + // Remember the previous bin and headers state here. + Map previous_bin_state; + Map previous_headers_state; + ToolBox tb = new ToolBox(); + + void test() throws Exception { + Files.createDirectory(GENSRC); + Files.createDirectory(BIN); + Files.createDirectory(HEADERS); + + initialCompile(); + incrementalCompileDroppingClasses(); + + clean(GENSRC, BIN, HEADERS); + } + + // Testing that deleting AA.java deletes all generated inner class including AA.class + void incrementalCompileDroppingClasses() throws Exception { + previous_bin_state = collectState(BIN); + previous_headers_state = collectState(HEADERS); + System.out.println("\nIn incrementalCompileDroppingClasses() "); + System.out.println("Testing that deleting AA.java deletes all generated inner class including AA.class"); + removeFrom(GENSRC, "alfa/omega/AA.java"); + compile("gensrc", "-d", "bin", "-h", "headers", "-j", "1", + SERVER_ARG, "--log=debug"); + Map new_bin_state = collectState(BIN); + verifyThatFilesHaveBeenRemoved(previous_bin_state, new_bin_state, + "bin/alfa/omega/AA$1.class", + "bin/alfa/omega/AA$AAAA.class", + "bin/alfa/omega/AA$AAA.class", + "bin/alfa/omega/AAAAA.class", + "bin/alfa/omega/AA.class"); + + previous_bin_state = new_bin_state; + Map new_headers_state = collectState(HEADERS); + verifyEqual(previous_headers_state, new_headers_state); + } +} diff --git a/langtools/test/tools/sjavac/IncCompileFullyQualifiedRef.java b/langtools/test/tools/sjavac/IncCompileFullyQualifiedRef.java new file mode 100644 index 00000000000..6f2e9187aaa --- /dev/null +++ b/langtools/test/tools/sjavac/IncCompileFullyQualifiedRef.java @@ -0,0 +1,79 @@ +/* + * 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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 + * @summary Verify that "alfa.omega.A a" does create a proper dependency + * @bug 8054689 + * @author Fredrik O + * @author sogoel (rewrite) + * @library /tools/lib + * @build Wrapper ToolBox + * @run main Wrapper IncCompileFullyQualifiedRef + */ + +import java.util.*; +import java.nio.file.*; + +public class IncCompileFullyQualifiedRef extends SJavacTester { + public static void main(String... args) throws Exception { + IncCompileFullyQualifiedRef fr = new IncCompileFullyQualifiedRef(); + fr.test(); + } + + void test() throws Exception { + ToolBox tb = new ToolBox(); + tb.writeFile(GENSRC.resolve("alfa/omega/A.java"), + "package alfa.omega; public class A { "+ + " public final static int DEFINITION = 18; "+ + " public void hello() { }"+ + "}"); + tb.writeFile(GENSRC.resolve("beta/B.java"), + "package beta; public class B { "+ + " public void world() { alfa.omega.A a; }"+ + "}"); + + compile("gensrc", "-d", "bin", "-j", "1", + SERVER_ARG, "--log=debug"); + Map previous_bin_state = collectState(BIN); + + // Change pubapi of A, this should trigger a recompile of B. + tb.writeFile(GENSRC.resolve("alfa/omega/A.java"), + "package alfa.omega; public class A { "+ + " public final static int DEFINITION = 19; "+ + " public void hello() { }"+ + "}"); + + compile("gensrc", "-d", "bin", "-j", "1", + SERVER_ARG, "--log=debug"); + Map new_bin_state = collectState(BIN); + + verifyNewerFiles(previous_bin_state, new_bin_state, + "bin/alfa/omega/A.class", + "bin/beta/B.class", + "bin/javac_state"); + clean(GENSRC,BIN); + } +} diff --git a/langtools/test/tools/sjavac/IncCompileNoChanges.java b/langtools/test/tools/sjavac/IncCompileNoChanges.java new file mode 100644 index 00000000000..78f4ea180dc --- /dev/null +++ b/langtools/test/tools/sjavac/IncCompileNoChanges.java @@ -0,0 +1,72 @@ +/* + * 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 + * @summary Verify no change in sources implies no change in binaries + * @bug 8054689 + * @author Fredrik O + * @author sogoel (rewrite) + * @library /tools/lib + * @build Wrapper ToolBox + * @run main Wrapper IncCompileNoChanges + */ + +import java.util.*; +import java.nio.file.*; + +public class IncCompileNoChanges extends SJavacTester { + public static void main(String... args) throws Exception { + IncCompileNoChanges nc = new IncCompileNoChanges(); + nc.test(); + } + + // Remember the previous bin and headers state here. + Map previous_bin_state; + Map previous_headers_state; + + void test() throws Exception { + Files.createDirectory(GENSRC); + Files.createDirectory(BIN); + Files.createDirectory(HEADERS); + + initialCompile(); + incrementalCompileNoChanges(); + + clean(GENSRC, BIN, HEADERS); + } + + // Testing that no change in sources implies no change in binaries + void incrementalCompileNoChanges() throws Exception { + previous_bin_state = collectState(BIN); + previous_headers_state = collectState(HEADERS); + System.out.println("\nIn incrementalCompileNoChanges() "); + System.out.println("Testing that no change in sources implies no change in binaries"); + compile("gensrc", "-d", "bin", "-h", "headers", "-j", "1", + SERVER_ARG, "--log=debug"); + Map new_bin_state = collectState(BIN); + verifyEqual(new_bin_state, previous_bin_state); + Map new_headers_state = collectState(HEADERS); + verifyEqual(previous_headers_state, new_headers_state); + } +} diff --git a/langtools/test/tools/sjavac/IncCompileUpdateNative.java b/langtools/test/tools/sjavac/IncCompileUpdateNative.java new file mode 100644 index 00000000000..d8eb7a4d4de --- /dev/null +++ b/langtools/test/tools/sjavac/IncCompileUpdateNative.java @@ -0,0 +1,86 @@ +/* + * 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 + * @summary Verify native files are rewritten + * @bug 8054689 + * @author Fredrik O + * @author sogoel (rewrite) + * @library /tools/lib + * @build Wrapper ToolBox + * @run main Wrapper IncCompileUpdateNative + */ + +import java.util.*; +import java.nio.file.*; + +public class IncCompileUpdateNative extends SJavacTester { + public static void main(String... args) throws Exception { + IncCompileUpdateNative un = new IncCompileUpdateNative(); + un.test(); + } + + // Remember the previous bin and headers state here. + Map previous_bin_state; + Map previous_headers_state; + ToolBox tb = new ToolBox(); + + void test() throws Exception { + Files.createDirectory(GENSRC); + Files.createDirectory(BIN); + Files.createDirectory(HEADERS); + + initialCompile(); + incrementalCompileChangeNative(); + + clean(GENSRC, BIN, HEADERS); + } + + // Update B.java with a new value for the final static annotated with @Native + // Verify that beta_B.h is rewritten again + void incrementalCompileChangeNative() throws Exception { + previous_bin_state = collectState(BIN); + previous_headers_state = collectState(HEADERS); + System.out.println("\nIn incrementalCompileChangeNative() "); + System.out.println("Verify that beta_B.h is rewritten again"); + tb.writeFile(GENSRC.resolve("beta/B.java"), + "package beta; import alfa.omega.A; public class B {"+ + "private int b() { return A.DEFINITION; } "+ + "@java.lang.annotation.Native final static int alfa = 43; }"); + + compile("gensrc", "-d", "bin", "-h", "headers", "-j", "1", + SERVER_ARG, "--log=debug"); + Map new_bin_state = collectState(BIN); + verifyNewerFiles(previous_bin_state, new_bin_state, + "bin/beta/B.class", + "bin/beta/BINT.class", + "bin/javac_state"); + previous_bin_state = new_bin_state; + + Map new_headers_state = collectState(HEADERS); + verifyNewerFiles(previous_headers_state, new_headers_state, + "headers/beta_B.h"); + previous_headers_state = new_headers_state; + } +} diff --git a/langtools/test/tools/sjavac/IncCompileWithChanges.java b/langtools/test/tools/sjavac/IncCompileWithChanges.java new file mode 100644 index 00000000000..a15a43ec36f --- /dev/null +++ b/langtools/test/tools/sjavac/IncCompileWithChanges.java @@ -0,0 +1,94 @@ +/* + * 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 + * @summary Verify incremental changes in gensrc are handled as expected + * @bug 8054689 + * @author Fredrik O + * @author sogoel (rewrite) + * @library /tools/lib + * @build Wrapper ToolBox + * @run main Wrapper IncCompileWithChanges + */ + +import java.util.*; +import java.nio.file.*; + +public class IncCompileWithChanges extends SJavacTester { + public static void main(String... args) throws Exception { + IncCompileWithChanges wc = new IncCompileWithChanges(); + wc.test(); + } + + // Remember the previous bin and headers state here. + Map previous_bin_state; + Map previous_headers_state; + ToolBox tb = new ToolBox(); + + void test() throws Exception { + Files.createDirectory(GENSRC); + Files.createDirectory(BIN); + Files.createDirectory(HEADERS); + + initialCompile(); + incrementalCompileWithChange(); + + clean(GENSRC, BIN, HEADERS); + } + + /* Update A.java with a new timestamp and new final static definition. + * This should trigger a recompile, not only of alfa, but also beta. + * Generated native header should not be updated since native api of B was not modified. + */ + void incrementalCompileWithChange() throws Exception { + previous_bin_state = collectState(BIN); + previous_headers_state = collectState(HEADERS); + System.out.println("\nIn incrementalCompileWithChange() "); + System.out.println("A.java updated to trigger a recompile"); + System.out.println("Generated native header should not be updated since native api of B was not modified"); + tb.writeFile(GENSRC.resolve("alfa/omega/A.java"), + "package alfa.omega; public class A implements AINT { "+ + "public final static int DEFINITION = 18; public void aint() { } private void foo() { } }"); + + compile("gensrc", "-d", "bin", "-h", "headers", "-j", "1", + SERVER_ARG, "--log=debug"); + Map new_bin_state = collectState(BIN); + + verifyNewerFiles(previous_bin_state, new_bin_state, + "bin/alfa/omega/A.class", + "bin/alfa/omega/AINT.class", + "bin/alfa/omega/AA$AAAA.class", + "bin/alfa/omega/AAAAA.class", + "bin/alfa/omega/AA$AAA.class", + "bin/alfa/omega/AA.class", + "bin/alfa/omega/AA$1.class", + "bin/beta/B.class", + "bin/beta/BINT.class", + "bin/javac_state"); + previous_bin_state = new_bin_state; + + Map new_headers_state = collectState(HEADERS); + verifyEqual(new_headers_state, previous_headers_state); + } +} diff --git a/langtools/test/tools/sjavac/PermittedArtifact.java b/langtools/test/tools/sjavac/PermittedArtifact.java new file mode 100644 index 00000000000..ef03b031cb5 --- /dev/null +++ b/langtools/test/tools/sjavac/PermittedArtifact.java @@ -0,0 +1,74 @@ +/* + * 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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 + * @summary Test white listing of external artifacts inside the destination dir + * @bug 8054689 + * @author Fredrik O + * @author sogoel (rewrite) + * @library /tools/lib + * @build Wrapper ToolBox + * @run main Wrapper PermittedArtifact + */ + +import java.lang.reflect.Method; +import java.util.*; +import java.io.*; +import java.nio.file.*; +import java.nio.file.attribute.*; +import java.nio.charset.*; + +public class PermittedArtifact extends SJavacTester { + public static void main(String... args) throws Exception { + PermittedArtifact pa = new PermittedArtifact(); + pa.test(); + } + + //Verify that --permit-artifact=bin works + void test() throws Exception { + Files.createDirectory(BIN); + clean(GENSRC, BIN); + + Map previous_bin_state = collectState(BIN); + + new ToolBox().writeFile(GENSRC+"/alfa/omega/A.java", + "package alfa.omega; public class A { }"); + + new ToolBox().writeFile(BIN+"/alfa/omega/AA.class", + "Ugh, a messy build system (tobefixed) wrote this class file, " + + "sjavac must not delete it."); + + compile("--log=debug", "--permit-artifact=bin/alfa/omega/AA.class", + "-src", "gensrc", "-d", "bin", SERVER_ARG); + + Map new_bin_state = collectState(BIN); + verifyThatFilesHaveBeenAdded(previous_bin_state, new_bin_state, + "bin/alfa/omega/A.class", + "bin/alfa/omega/AA.class", + "bin/javac_state"); + clean(GENSRC, BIN); + } +} diff --git a/langtools/test/tools/sjavac/SJavac.java b/langtools/test/tools/sjavac/SJavac.java deleted file mode 100644 index 90ac8b7d711..00000000000 --- a/langtools/test/tools/sjavac/SJavac.java +++ /dev/null @@ -1,746 +0,0 @@ -/* - * 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 - * @summary Test all aspects of sjavac. - * @bug 8004658 8042441 8042699 8054461 8054474 8054465 - * - * @build Wrapper - * @run main Wrapper SJavac - */ - -import java.util.*; -import java.io.*; -import java.nio.file.*; -import java.nio.file.attribute.*; -import java.nio.charset.*; - -import com.sun.tools.sjavac.Main; - -public class SJavac { - - public static void main(String... args) throws Exception { - try { - SJavac s = new SJavac(); - s.test(); - } finally { - System.out.println("\ntest complete\n"); - } - } - - FileSystem defaultfs = FileSystems.getDefault(); - String serverArg = "--server:" - + "portfile=testportfile," - + "background=false"; - - // Where to put generated sources that will - // test aspects of sjavac, ie JTWork/scratch/gensrc - Path gensrc; - // More gensrc dirs are used to test merging of serveral source roots. - Path gensrc2; - Path gensrc3; - - // Where to put compiled classes. - Path bin; - // Where to put c-header files. - Path headers; - - // Remember the previous bin and headers state here. - Map previous_bin_state; - Map previous_headers_state; - - public void test() throws Exception { - gensrc = defaultfs.getPath("gensrc"); - gensrc2 = defaultfs.getPath("gensrc2"); - gensrc3 = defaultfs.getPath("gensrc3"); - bin = defaultfs.getPath("bin"); - headers = defaultfs.getPath("headers"); - - Files.createDirectory(gensrc); - Files.createDirectory(gensrc2); - Files.createDirectory(gensrc3); - Files.createDirectory(bin); - Files.createDirectory(headers); - - initialCompile(); - incrementalCompileNoChanges(); - incrementalCompileDroppingClasses(); - incrementalCompileWithChange(); - incrementalCompileDropAllNatives(); - incrementalCompileAddNative(); - incrementalCompileChangeNative(); - compileWithOverrideSource(); - compileWithInvisibleSources(); - compileCircularSources(); - compileExcludingDependency(); - incrementalCompileTestFullyQualifiedRef(); - compileWithAtFile(); - testStateDir(); - testPermittedArtifact(); - - delete(gensrc); - delete(gensrc2); - delete(gensrc3); - delete(bin); - delete(headers); - } - - void initialCompile() throws Exception { - System.out.println("\nInitial compile of gensrc."); - System.out.println("----------------------------"); - populate(gensrc, - "alfa/omega/AINT.java", - "package alfa.omega; public interface AINT { void aint(); }", - - "alfa/omega/A.java", - "package alfa.omega; public class A implements AINT { "+ - "public final static int DEFINITION = 17; public void aint() { } }", - - "alfa/omega/AA.java", - "package alfa.omega;"+ - "// A package private class, not contributing to the public api.\n"+ - "class AA {"+ - " // A properly nested static inner class.\n"+ - " static class AAA { }\n"+ - " // A properly nested inner class.\n"+ - " class AAAA { }\n"+ - " Runnable foo() {\n"+ - " // A proper anonymous class.\n"+ - " return new Runnable() { public void run() { } };\n"+ - " }\n"+ - " AAA aaa;\n"+ - " AAAA aaaa;\n"+ - " AAAAA aaaaa;\n"+ - "}\n"+ - "class AAAAA {\n"+ - " // A bad auxiliary class, but no one is referencing it\n"+ - " // from outside of this source file, therefore it is ok.\n"+ - "}\n", - - "beta/BINT.java", - "package beta;public interface BINT { void foo(); }", - - "beta/B.java", - "package beta; import alfa.omega.A; public class B {"+ - "private int b() { return A.DEFINITION; } native void foo(); }"); - - compile("gensrc", "-d", "bin", "-h", "headers", "-j", "1", - serverArg, "--log=debug"); - previous_bin_state = collectState(bin); - previous_headers_state = collectState(headers); - } - - void incrementalCompileNoChanges() throws Exception { - System.out.println("\nTesting that no change in sources implies no change in binaries."); - System.out.println("------------------------------------------------------------------"); - compile("gensrc", "-d", "bin", "-h", "headers", "-j", "1", - serverArg, "--log=debug"); - Map new_bin_state = collectState(bin); - verifyEqual(new_bin_state, previous_bin_state); - Map new_headers_state = collectState(headers); - verifyEqual(previous_headers_state, new_headers_state); - } - - void incrementalCompileDroppingClasses() throws Exception { - System.out.println("\nTesting that deleting AA.java deletes all"); - System.out.println("generated inner class as well as AA.class"); - System.out.println("-----------------------------------------"); - removeFrom(gensrc, "alfa/omega/AA.java"); - compile("gensrc", "-d", "bin", "-h", "headers", "-j", "1", - serverArg, "--log=debug"); - Map new_bin_state = collectState(bin); - verifyThatFilesHaveBeenRemoved(previous_bin_state, new_bin_state, - "bin/alfa/omega/AA$1.class", - "bin/alfa/omega/AA$AAAA.class", - "bin/alfa/omega/AA$AAA.class", - "bin/alfa/omega/AAAAA.class", - "bin/alfa/omega/AA.class"); - - previous_bin_state = new_bin_state; - Map new_headers_state = collectState(headers); - verifyEqual(previous_headers_state, new_headers_state); - } - - void incrementalCompileWithChange() throws Exception { - System.out.println("\nNow update the A.java file with a new timestamps and"); - System.out.println("new final static definition. This should trigger a recompile,"); - System.out.println("not only of alfa, but also beta."); - System.out.println("But check that the generated native header was not updated!"); - System.out.println("Since we did not modify the native api of B."); - System.out.println("-------------------------------------------------------------"); - - populate(gensrc,"alfa/omega/A.java", - "package alfa.omega; public class A implements AINT { "+ - "public final static int DEFINITION = 18; public void aint() { } private void foo() { } }"); - - compile("gensrc", "-d", "bin", "-h", "headers", "-j", "1", - serverArg, "--log=debug"); - Map new_bin_state = collectState(bin); - - verifyNewerFiles(previous_bin_state, new_bin_state, - "bin/alfa/omega/A.class", - "bin/alfa/omega/AINT.class", - "bin/beta/B.class", - "bin/beta/BINT.class", - "bin/javac_state"); - previous_bin_state = new_bin_state; - - Map new_headers_state = collectState(headers); - verifyEqual(new_headers_state, previous_headers_state); - } - - void incrementalCompileDropAllNatives() throws Exception { - System.out.println("\nNow update the B.java file with one less native method,"); - System.out.println("ie it has no longer any methods!"); - System.out.println("Verify that beta_B.h is removed!"); - System.out.println("---------------------------------------------------------"); - - populate(gensrc,"beta/B.java", - "package beta; import alfa.omega.A; public class B {"+ - "private int b() { return A.DEFINITION; } }"); - - compile("gensrc", "-d", "bin", "-h", "headers", "-j", "1", - serverArg, "--log=debug"); - Map new_bin_state = collectState(bin); - verifyNewerFiles(previous_bin_state, new_bin_state, - "bin/beta/B.class", - "bin/beta/BINT.class", - "bin/javac_state"); - previous_bin_state = new_bin_state; - - Map new_headers_state = collectState(headers); - verifyThatFilesHaveBeenRemoved(previous_headers_state, new_headers_state, - "headers/beta_B.h"); - previous_headers_state = new_headers_state; - } - - void incrementalCompileAddNative() throws Exception { - System.out.println("\nNow update the B.java file with a final static annotated with @Native."); - System.out.println("Verify that beta_B.h is added again!"); - System.out.println("------------------------------------------------------------------------"); - - populate(gensrc,"beta/B.java", - "package beta; import alfa.omega.A; public class B {"+ - "private int b() { return A.DEFINITION; } "+ - "@java.lang.annotation.Native final static int alfa = 42; }"); - - compile("gensrc", "-d", "bin", "-h", "headers", "-j", "1", - serverArg, "--log=debug"); - Map new_bin_state = collectState(bin); - verifyNewerFiles(previous_bin_state, new_bin_state, - "bin/beta/B.class", - "bin/beta/BINT.class", - "bin/javac_state"); - previous_bin_state = new_bin_state; - - Map new_headers_state = collectState(headers); - verifyThatFilesHaveBeenAdded(previous_headers_state, new_headers_state, - "headers/beta_B.h"); - previous_headers_state = new_headers_state; - } - - void incrementalCompileChangeNative() throws Exception { - System.out.println("\nNow update the B.java file with a new value for the final static"+ - " annotated with @Native."); - System.out.println("Verify that beta_B.h is rewritten again!"); - System.out.println("-------------------------------------------------------------------"); - - populate(gensrc,"beta/B.java", - "package beta; import alfa.omega.A; public class B {"+ - "private int b() { return A.DEFINITION; } "+ - "@java.lang.annotation.Native final static int alfa = 43; }"); - - compile("gensrc", "-d", "bin", "-h", "headers", "-j", "1", - serverArg, "--log=debug"); - Map new_bin_state = collectState(bin); - verifyNewerFiles(previous_bin_state, new_bin_state, - "bin/beta/B.class", - "bin/beta/BINT.class", - "bin/javac_state"); - previous_bin_state = new_bin_state; - - Map new_headers_state = collectState(headers); - verifyNewerFiles(previous_headers_state, new_headers_state, - "headers/beta_B.h"); - previous_headers_state = new_headers_state; - } - - void compileWithOverrideSource() throws Exception { - System.out.println("\nNow verify that we can override sources to be compiled."); - System.out.println("Compile gensrc and gensrc2. However do not compile broken beta.B in gensrc,"); - System.out.println("only compile ok beta.B in gensrc2."); - System.out.println("---------------------------------------------------------------------------"); - - delete(gensrc); - delete(gensrc2); - delete(bin); - previous_bin_state = collectState(bin); - - populate(gensrc,"alfa/omega/A.java", - "package alfa.omega; import beta.B; import gamma.C; public class A { B b; C c; }", - "beta/B.java", - "package beta; public class B { broken", - "gamma/C.java", - "package gamma; public class C { }"); - - populate(gensrc2, - "beta/B.java", - "package beta; public class B { }"); - - compile("-x", "beta", "gensrc", "gensrc2", "-d", "bin", "-h", "headers", "-j", "1", - serverArg); - Map new_bin_state = collectState(bin); - verifyThatFilesHaveBeenAdded(previous_bin_state, new_bin_state, - "bin/alfa/omega/A.class", - "bin/beta/B.class", - "bin/gamma/C.class", - "bin/javac_state"); - - System.out.println("----- Compile with exluded beta went well!"); - delete(bin); - compileExpectFailure("gensrc", "gensrc2", "-d", "bin", "-h", "headers", "-j", "1", - serverArg); - - System.out.println("----- Compile without exluded beta failed, as expected! Good!"); - delete(bin); - } - - void compileWithInvisibleSources() throws Exception { - System.out.println("\nNow verify that we can make sources invisible to linking (sourcepath)."); - System.out.println("Compile gensrc and link against gensrc2 and gensrc3, however"); - System.out.println("gensrc2 contains broken code in beta.B, thus we must exclude that package"); - System.out.println("fortunately gensrc3 contains a proper beta.B."); - System.out.println("------------------------------------------------------------------------"); - - // Start with a fresh gensrcs and bin. - delete(gensrc); - delete(gensrc2); - delete(gensrc3); - delete(bin); - previous_bin_state = collectState(bin); - - populate(gensrc,"alfa/omega/A.java", - "package alfa.omega; import beta.B; import gamma.C; public class A { B b; C c; }"); - populate(gensrc2,"beta/B.java", - "package beta; public class B { broken", - "gamma/C.java", - "package gamma; public class C { }"); - populate(gensrc3, "beta/B.java", - "package beta; public class B { }"); - - compile("gensrc", "-x", "beta", "-sourcepath", "gensrc2", - "-sourcepath", "gensrc3", "-d", "bin", "-h", "headers", "-j", "1", - serverArg); - - System.out.println("The first compile went well!"); - Map new_bin_state = collectState(bin); - verifyThatFilesHaveBeenAdded(previous_bin_state, new_bin_state, - "bin/alfa/omega/A.class", - "bin/javac_state"); - - System.out.println("----- Compile with exluded beta went well!"); - delete(bin); - compileExpectFailure("gensrc", "-sourcepath", "gensrc2", "-sourcepath", "gensrc3", - "-d", "bin", "-h", "headers", "-j", "1", - serverArg); - - System.out.println("----- Compile without exluded beta failed, as expected! Good!"); - delete(bin); - } - - void compileCircularSources() throws Exception { - System.out.println("\nNow verify that circular sources split on multiple cores can be compiled."); - System.out.println("---------------------------------------------------------------------------"); - - // Start with a fresh gensrcs and bin. - delete(gensrc); - delete(gensrc2); - delete(gensrc3); - delete(bin); - previous_bin_state = collectState(bin); - - populate(gensrc,"alfa/omega/A.java", - "package alfa.omega; public class A { beta.B b; }", - "beta/B.java", - "package beta; public class B { gamma.C c; }", - "gamma/C.java", - "package gamma; public class C { alfa.omega.A a; }"); - - compile("gensrc", "-d", "bin", "-h", "headers", "-j", "3", - serverArg,"--log=debug"); - Map new_bin_state = collectState(bin); - verifyThatFilesHaveBeenAdded(previous_bin_state, new_bin_state, - "bin/alfa/omega/A.class", - "bin/beta/B.class", - "bin/gamma/C.class", - "bin/javac_state"); - delete(bin); - } - - /** - * Tests compiling class A that depends on class B without compiling class B - * @throws Exception If test fails - */ - void compileExcludingDependency() throws Exception { - System.out.println("\nVerify that excluding classes from compilation but not from linking works."); - System.out.println("---------------------------------------------------------------------------"); - - delete(gensrc); - delete(bin); - previous_bin_state = collectState(bin); - - populate(gensrc, - "alfa/omega/A.java", - "package alfa.omega; public class A { beta.B b; }", - "beta/B.java", - "package beta; public class B { }"); - - compile("-x", "beta", "-src", "gensrc", "-x", "alfa/omega", "-sourcepath", "gensrc", - "-d", "bin", serverArg); - - Map new_bin_state = collectState(bin); - verifyThatFilesHaveBeenAdded(previous_bin_state, new_bin_state, - "bin/alfa/omega/A.class", - "bin/javac_state"); - } - - void incrementalCompileTestFullyQualifiedRef() throws Exception { - System.out.println("\nVerify that \"alfa.omega.A a;\" does create a proper dependency."); - System.out.println("----------------------------------------------------------------"); - - populate(gensrc, - "alfa/omega/A.java", - "package alfa.omega; public class A { "+ - " public final static int DEFINITION = 18; "+ - " public void hello() { }"+ - "}", - "beta/B.java", - "package beta; public class B { "+ - " public void world() { alfa.omega.A a; }"+ - "}"); - - compile("gensrc", "-d", "bin", "-j", "1", - serverArg, "--log=debug"); - Map previous_bin_state = collectState(bin); - - // Change pubapi of A, this should trigger a recompile of B. - populate(gensrc, - "alfa/omega/A.java", - "package alfa.omega; public class A { "+ - " public final static int DEFINITION = 19; "+ - " public void hello() { }"+ - "}"); - - compile("gensrc", "-d", "bin", "-j", "1", - serverArg, "--log=debug"); - Map new_bin_state = collectState(bin); - - verifyNewerFiles(previous_bin_state, new_bin_state, - "bin/alfa/omega/A.class", - "bin/beta/B.class", - "bin/javac_state"); - } - - /** - * Tests @atfile - * @throws Exception If test fails - */ - void compileWithAtFile() throws Exception { - System.out.println("\nTest @atfile with command line content."); - System.out.println("---------------------------------------"); - - delete(gensrc); - delete(gensrc2); - delete(bin); - - populate(gensrc, - "list.txt", - "-if */alfa/omega/A.java\n-if */beta/B.java\ngensrc\n-d bin\n", - "alfa/omega/A.java", - "package alfa.omega; import beta.B; public class A { B b; }", - "beta/B.java", - "package beta; public class B { }", - "beta/C.java", - "broken"); - previous_bin_state = collectState(bin); - compile("@gensrc/list.txt", "--server:portfile=testserver,background=false"); - - Map new_bin_state = collectState(bin); - verifyThatFilesHaveBeenAdded(previous_bin_state, new_bin_state, - "bin/javac_state", - "bin/alfa/omega/A.class", - "bin/beta/B.class"); - } - - /** - * Tests storing javac_state into another directory. - * @throws Exception If test fails - */ - void testStateDir() throws Exception { - System.out.println("\nVerify that --state-dir=bar works."); - System.out.println("----------------------------------"); - - Path bar = defaultfs.getPath("bar"); - Files.createDirectory(bar); - - delete(gensrc); - delete(bin); - delete(bar); - previous_bin_state = collectState(bin); - Map previous_bar_state = collectState(bar); - - populate(gensrc, - "alfa/omega/A.java", - "package alfa.omega; public class A { }"); - - compile("--state-dir=bar", "-src", "gensrc", "-d", "bin", serverArg); - - Map new_bin_state = collectState(bin); - verifyThatFilesHaveBeenAdded(previous_bin_state, new_bin_state, - "bin/alfa/omega/A.class"); - Map new_bar_state = collectState(bar); - verifyThatFilesHaveBeenAdded(previous_bar_state, new_bar_state, - "bar/javac_state"); - } - - /** - * Test white listing of external artifacts inside the destination dir. - * @throws Exception If test fails - */ - void testPermittedArtifact() throws Exception { - System.out.println("\nVerify that --permit-artifact=bar works."); - System.out.println("-------------------------------------------"); - - delete(gensrc); - delete(bin); - - previous_bin_state = collectState(bin); - - populate(gensrc, - "alfa/omega/A.java", - "package alfa.omega; public class A { }"); - - populate(bin, - "alfa/omega/AA.class", - "Ugh, a messy build system (tobefixed) wrote this class file, sjavac must not delete it."); - - compile("--log=debug", "--permit-artifact=bin/alfa/omega/AA.class", "-src", "gensrc", "-d", "bin", serverArg); - - Map new_bin_state = collectState(bin); - verifyThatFilesHaveBeenAdded(previous_bin_state, new_bin_state, - "bin/alfa/omega/A.class", - "bin/alfa/omega/AA.class", - "bin/javac_state"); - } - - void removeFrom(Path dir, String... args) throws IOException { - for (String filename : args) { - Path p = dir.resolve(filename); - Files.delete(p); - } - } - - void populate(Path src, String... args) throws IOException { - if (!Files.exists(src)) { - Files.createDirectory(src); - } - String[] a = args; - for (int i = 0; i() { - @Override - public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException - { - Files.delete(file); - return FileVisitResult.CONTINUE; - } - - @Override - public FileVisitResult postVisitDirectory(Path dir, IOException e) throws IOException - { - if (e == null) { - if (!dir.equals(root)) Files.delete(dir); - return FileVisitResult.CONTINUE; - } else { - // directory iteration failed - throw e; - } - } - }); - } - - void compile(String... args) throws Exception { - int rc = Main.go(args); - if (rc != 0) throw new Exception("Error during compile!"); - - // Wait a second, to get around the (temporary) problem with - // second resolution in the Java file api. But do not do this - // on windows where the timestamps work. - long in_a_sec = System.currentTimeMillis()+1000; - while (in_a_sec > System.currentTimeMillis()) { - try { - Thread.sleep(1000); - } catch (InterruptedException e) { - } - } - } - - void compileExpectFailure(String... args) throws Exception { - int rc = Main.go(args); - if (rc == 0) throw new Exception("Expected error during compile! Did not fail!"); - } - - Map collectState(Path dir) throws IOException { - final Map files = new HashMap<>(); - Files.walkFileTree(dir, new SimpleFileVisitor() { - @Override - public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) - throws IOException - { - files.put(file.toString(),new Long(Files.getLastModifiedTime(file).toMillis())); - return FileVisitResult.CONTINUE; - } - }); - return files; - } - - void verifyThatFilesHaveBeenRemoved(Map from, - Map to, - String... args) throws Exception { - - Set froms = from.keySet(); - Set tos = to.keySet(); - - if (froms.equals(tos)) { - throw new Exception("Expected new state to have fewer files than previous state!"); - } - - for (String t : tos) { - if (!froms.contains(t)) { - throw new Exception("Expected "+t+" to exist in previous state!"); - } - } - - for (String f : args) { - f = f.replace("/", File.separator); - if (!froms.contains(f)) { - throw new Exception("Expected "+f+" to exist in previous state!"); - } - if (tos.contains(f)) { - throw new Exception("Expected "+f+" to have been removed from the new state!"); - } - } - - if (froms.size() - args.length != tos.size()) { - throw new Exception("There are more removed files than the expected list!"); - } - } - - void verifyThatFilesHaveBeenAdded(Map from, - Map to, - String... args) throws Exception { - - Set froms = from.keySet(); - Set tos = to.keySet(); - - if (froms.equals(tos)) { - throw new Exception("Expected new state to have more files than previous state!"); - } - - for (String t : froms) { - if (!tos.contains(t)) { - throw new Exception("Expected "+t+" to exist in new state!"); - } - } - - for (String f : args) { - f = f.replace("/", File.separator); - if (!tos.contains(f)) { - throw new Exception("Expected "+f+" to have been added to new state!"); - } - if (froms.contains(f)) { - throw new Exception("Expected "+f+" to not exist in previous state!"); - } - } - - if (froms.size() + args.length != tos.size()) { - throw new Exception("There are more added files than the expected list!"); - } - } - - void verifyNewerFiles(Map from, - Map to, - String... args) throws Exception { - if (!from.keySet().equals(to.keySet())) { - throw new Exception("Expected the set of files to be identical!"); - } - Set files = new HashSet(); - for (String s : args) { - files.add(s.replace("/", File.separator)); - } - for (String fn : from.keySet()) { - long f = from.get(fn); - long t = to.get(fn); - if (files.contains(fn)) { - if (t <= f) { - throw new Exception("Expected "+fn+" to have a more recent timestamp!"); - } - } else { - if (t != f) { - throw new Exception("Expected "+fn+" to have the same timestamp!"); - } - } - } - } - - String print(Map m) { - StringBuilder b = new StringBuilder(); - Set keys = m.keySet(); - for (String k : keys) { - b.append(k+" "+m.get(k)+"\n"); - } - return b.toString(); - } - - void verifyEqual(Map from, Map to) throws Exception { - if (!from.equals(to)) { - System.out.println("FROM---"+print(from)); - System.out.println("TO-----"+print(to)); - throw new Exception("The dir should not differ! But it does!"); - } - } -} diff --git a/langtools/test/tools/sjavac/SJavacTester.java b/langtools/test/tools/sjavac/SJavacTester.java new file mode 100644 index 00000000000..f732ffa8ff7 --- /dev/null +++ b/langtools/test/tools/sjavac/SJavacTester.java @@ -0,0 +1,268 @@ +/* + * 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 java.util.*; +import java.io.*; +import java.nio.file.*; +import java.nio.file.attribute.*; +import java.nio.charset.*; + +import com.sun.tools.sjavac.Main; + +public class SJavacTester { + + static final String SERVER_ARG = "--server:" + + "portfile=testportfile," + + "background=false"; + + // Generated sources that will test aspects of sjavac + static final Path GENSRC = Paths.get("gensrc"); + // Gensrc dirs used to test merging of serveral source roots. + static final Path GENSRC2 = Paths.get("gensrc2"); + static final Path GENSRC3= Paths.get("gensrc3"); + + // Dir for compiled classes. + static final Path BIN = Paths.get("bin"); + // Dir for c-header files. + Path HEADERS = Paths.get("headers"); + + // Remember the previous bin and headers state here. + Map previous_bin_state; + Map previous_headers_state; + + void initialCompile() throws Exception { + System.out.println("\nInitial compile of gensrc."); + ToolBox tb = new ToolBox(); + tb.writeFile(GENSRC.resolve("alfa/omega/AINT.java"), + "package alfa.omega; public interface AINT { void aint(); }"); + tb.writeFile(GENSRC.resolve("alfa/omega/A.java"), + "package alfa.omega; public class A implements AINT { "+ + "public final static int DEFINITION = 17; public void aint() { } }"); + tb.writeFile(GENSRC.resolve("alfa/omega/AA.java"), + "package alfa.omega;"+ + "// A package private class, not contributing to the public api.\n"+ + "class AA {"+ + " // A properly nested static inner class.\n"+ + " static class AAA { }\n"+ + " // A properly nested inner class.\n"+ + " class AAAA { }\n"+ + " Runnable foo() {\n"+ + " // A proper anonymous class.\n"+ + " return new Runnable() { public void run() { } };\n"+ + " }\n"+ + " AAA aaa;\n"+ + " AAAA aaaa;\n"+ + " AAAAA aaaaa;\n"+ + "}\n"+ + "class AAAAA {\n"+ + " // A bad auxiliary class, but no one is referencing it\n"+ + " // from outside of this source file, therefore it is ok.\n"+ + "}\n"); + tb.writeFile(GENSRC.resolve("beta/BINT.java"), + "package beta;public interface BINT { void foo(); }"); + tb.writeFile(GENSRC.resolve("beta/B.java"), + "package beta; import alfa.omega.A; public class B {"+ + "private int b() { return A.DEFINITION; } native void foo(); }"); + + compile("gensrc", "-d", "bin", "-h", "headers", "-j", "1", + SERVER_ARG, "--log=debug"); + } + + void removeFrom(Path dir, String... args) throws IOException { + for (String filename : args) { + Path p = dir.resolve(filename); + Files.delete(p); + } + } + + void delete(final Path root) throws IOException { + if (!Files.exists(root)) return; + Files.walkFileTree(root, new SimpleFileVisitor() { + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException + { + Files.delete(file); + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult postVisitDirectory(Path dir, IOException e) throws IOException + { + if (e == null) { + if (!dir.equals(root)) Files.delete(dir); + return FileVisitResult.CONTINUE; + } else { + // directory iteration failed + throw e; + } + } + }); + } + + void compile(String... args) throws Exception { + int rc = Main.go(args); + if (rc != 0) throw new Exception("Error during compile!"); + + // Wait a second, to get around the (temporary) problem with + // second resolution in the Java file api. But do not do this + // on windows where the timestamps work. + long in_a_sec = System.currentTimeMillis()+1000; + while (in_a_sec > System.currentTimeMillis()) { + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + } + } + } + + void compileExpectFailure(String... args) throws Exception { + int rc = Main.go(args); + if (rc == 0) throw new Exception("Expected error during compile! Did not fail!"); + } + + Map collectState(Path dir) throws IOException { + final Map files = new HashMap<>(); + Files.walkFileTree(dir, new SimpleFileVisitor() { + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) + throws IOException + { + files.put(file.toString(),new Long(Files.getLastModifiedTime(file).toMillis())); + return FileVisitResult.CONTINUE; + } + }); + return files; + } + + void verifyThatFilesHaveBeenRemoved(Map from, + Map to, + String... args) throws Exception { + + Set froms = from.keySet(); + Set tos = to.keySet(); + + if (froms.equals(tos)) { + throw new Exception("Expected new state to have fewer files than previous state!"); + } + + for (String t : tos) { + if (!froms.contains(t)) { + throw new Exception("Expected "+t+" to exist in previous state!"); + } + } + + for (String f : args) { + f = f.replace("/", File.separator); + if (!froms.contains(f)) { + throw new Exception("Expected "+f+" to exist in previous state!"); + } + if (tos.contains(f)) { + throw new Exception("Expected "+f+" to have been removed from the new state!"); + } + } + + if (froms.size() - args.length != tos.size()) { + throw new Exception("There are more removed files than the expected list!"); + } + } + + void verifyThatFilesHaveBeenAdded(Map from, + Map to, + String... args) throws Exception { + + Set froms = from.keySet(); + Set tos = to.keySet(); + + if (froms.equals(tos)) { + throw new Exception("Expected new state to have more files than previous state!"); + } + + for (String t : froms) { + if (!tos.contains(t)) { + throw new Exception("Expected "+t+" to exist in new state!"); + } + } + + for (String f : args) { + f = f.replace("/", File.separator); + if (!tos.contains(f)) { + throw new Exception("Expected "+f+" to have been added to new state!"); + } + if (froms.contains(f)) { + throw new Exception("Expected "+f+" to not exist in previous state!"); + } + } + + if (froms.size() + args.length != tos.size()) { + throw new Exception("There are more added files than the expected list!"); + } + } + + void verifyNewerFiles(Map from, + Map to, + String... args) throws Exception { + if (!from.keySet().equals(to.keySet())) { + throw new Exception("Expected the set of files to be identical!"); + } + Set files = new HashSet(); + for (String s : args) { + files.add(s.replace("/", File.separator)); + } + for (String fn : from.keySet()) { + long f = from.get(fn); + long t = to.get(fn); + if (files.contains(fn)) { + if (t <= f) { + throw new Exception("Expected "+fn+" to have a more recent timestamp!"); + } + } else { + if (t != f) { + throw new Exception("Expected "+fn+" to have the same timestamp!"); + } + } + } + } + + String print(Map m) { + StringBuilder b = new StringBuilder(); + Set keys = m.keySet(); + for (String k : keys) { + b.append(k+" "+m.get(k)+"\n"); + } + return b.toString(); + } + + void verifyEqual(Map from, Map to) throws Exception { + if (!from.equals(to)) { + System.out.println("FROM---"+print(from)); + System.out.println("TO-----"+print(to)); + throw new Exception("The dir should not differ! But it does!"); + } + } + + void clean(Path... listOfDirs) throws Exception { + for (Path dir : listOfDirs) { + delete(dir); + } + } +} diff --git a/langtools/test/tools/sjavac/StateDir.java b/langtools/test/tools/sjavac/StateDir.java new file mode 100644 index 00000000000..b1710782885 --- /dev/null +++ b/langtools/test/tools/sjavac/StateDir.java @@ -0,0 +1,71 @@ +/* + * 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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 + * @summary Verify that --state-dir=bar works + * @bug 8054689 + * @author Fredrik O + * @author sogoel (rewrite) + * @library /tools/lib + * @build Wrapper ToolBox + * @run main Wrapper StateDir + */ + +import java.util.*; +import java.nio.file.*; + +public class StateDir extends SJavacTester { + public static void main(String... args) throws Exception { + StateDir sd = new StateDir(); + sd.test(); + } + + void test() throws Exception { + Path bar = Paths.get("bar"); + Files.createDirectory(bar); + Files.createDirectory(BIN); + + clean(GENSRC, BIN, bar); + + Map previous_bin_state = collectState(BIN); + Map previous_bar_state = collectState(bar); + + ToolBox tb = new ToolBox(); + tb.writeFile(GENSRC.resolve("alfa/omega/A.java"), + "package alfa.omega; public class A { }"); + + compile("--state-dir=bar", "-src", "gensrc", "-d", "bin", + SJavacTester.SERVER_ARG); + + Map new_bin_state = collectState(BIN); + verifyThatFilesHaveBeenAdded(previous_bin_state, new_bin_state, + "bin/alfa/omega/A.class"); + Map new_bar_state = collectState(bar); + verifyThatFilesHaveBeenAdded(previous_bar_state, new_bar_state, + "bar/javac_state"); + clean(GENSRC, BIN, bar); + } +} diff --git a/make/Javadoc.gmk b/make/Javadoc.gmk index d68c6f333ce..a12d0df7cee 100644 --- a/make/Javadoc.gmk +++ b/make/Javadoc.gmk @@ -53,8 +53,7 @@ BUILD_NUMBER=$(JDK_BUILD_NUMBER) JAVADOC_CMD = $(JAVA) \ -Djava.awt.headless=true \ - $(NEW_JAVADOC) \ - -bootclasspath $(JDK_OUTPUTDIR)/classes + $(NEW_JAVADOC) # Copyright year for beginning of Java and some of the apis # (Needed when creating the javadocs) @@ -231,17 +230,17 @@ endef # Common echo of option define OptionOnly # opt - if [ "$1" != "" ] ; then \ - $(PRINTF) "%s\n" "$1"; \ + if [ "$(strip $1)" != "" ] ; then \ + $(PRINTF) "%s\n" "$(strip $1)"; \ fi endef define OptionPair # opt arg - $(PRINTF) "%s '%s'\n" "$1" '$2' + $(PRINTF) "%s '%s'\n" "$(strip $1)" '$(strip $2)' endef define OptionTrip # opt arg arg - $(PRINTF) "%s '%s' '%s'\n" "$1" '$2' '$3' + $(PRINTF) "%s '%s' '%s'\n" "$(strip $1)" '$(strip $2)' '$(strip $3)' endef # Core api bottom argument (with special sauce) diff --git a/make/Main.gmk b/make/Main.gmk index ba4ba3c2219..0f705491b0a 100644 --- a/make/Main.gmk +++ b/make/Main.gmk @@ -257,7 +257,7 @@ ALL_TARGETS += docs-javadoc docs-jvmtidoc test: ($(CD) $(SRC_ROOT)/test && $(MAKE) $(MAKE_ARGS) -j1 -k MAKEFLAGS= \ - JT_HOME=$(JT_HOME) PRODUCT_HOME=$(JDK_OUTPUTDIR) \ + JT_HOME=$(JT_HOME) PRODUCT_HOME=$(JDK_IMAGE_DIR) \ ALT_OUTPUTDIR=$(OUTPUT_ROOT) CONCURRENCY=$(JOBS) $(TEST)) || true test-make: @@ -394,7 +394,7 @@ else docs-jvmtidoc: hotspot - test: exploded-image + test: jimages verify-modules: exploded-image diff --git a/make/StripBinaries.gmk b/make/StripBinaries.gmk index 92bb17159a2..c05e2a1eef1 100644 --- a/make/StripBinaries.gmk +++ b/make/StripBinaries.gmk @@ -66,11 +66,6 @@ STRIP_LIBS_SRC := \ $(shell $(FIND) $(SUPPORT_OUTPUTDIR)/modules_libs \ -name '*$(SHARED_LIBRARY_SUFFIX)' -type f) -# On Windows, don't include debug info for libs either. -ifeq ($(OPENJDK_TARGET_OS), windows) - COPY_LIBS_SRC := $(filter-out %.diz %.map %.pdb, $(COPY_LIBS_SRC)) -endif - $(eval $(call SetupCopyFiles,STRIP_MODULES_CMDS, \ SRC := $(SUPPORT_OUTPUTDIR)/modules_cmds, \ DEST := $(MODULES_CMDS_STRIPPED), \ diff --git a/make/jprt.properties b/make/jprt.properties index fdb18513f52..d9cd1498649 100644 --- a/make/jprt.properties +++ b/make/jprt.properties @@ -188,6 +188,13 @@ my.make.rule.test.targets.svc= \ ${my.test.target.set:TESTNAME=svc_tools}, \ ${my.make.rule.test.targets.svc.extra} +# JAXP vm test targets (testset=jaxp) +my.test.targets.jaxp= + +# JAXP test targets (testset=jaxp) +my.make.rule.test.targets.jaxp= \ + ${my.test.target.set:TESTNAME=jaxp_all} + # All vm test targets (testset=all) my.test.targets.all= \ ${my.test.targets.default}, \ @@ -211,7 +218,8 @@ my.test.targets.pit= \ my.make.rule.test.targets.pit= \ ${my.test.target.set:TESTNAME=langtools_jtreg}, \ ${my.make.rule.test.targets.core}, \ - ${my.make.rule.test.targets.svc} + ${my.make.rule.test.targets.svc} \ + ${my.make.rule.test.targets.jaxp} # JCK test targets in test/Makefile (no windows) my.test.target.set.jck= \ diff --git a/nashorn/.hgtags b/nashorn/.hgtags index e5dd9ffa61b..e00c3fdde79 100644 --- a/nashorn/.hgtags +++ b/nashorn/.hgtags @@ -276,3 +276,5 @@ dd7bbdf81a537106cfa9227d1a9a57849cb26b4d jdk9-b37 74dcd8dbef252938d6deb032aefb46b8f452dd9e jdk9-b40 52340a35aec9955d4aeaaf01d6337284f179b31c jdk9-b41 498d1d6c4219086143b764b3bf61afe65dcece47 jdk9-b42 +8ae8dff2a28f3b8831cce97ae0c7a957c5dc650a jdk9-b43 +50ee576062726e536d1bb9a5eadd8fd4470128fc jdk9-b44 diff --git a/nashorn/make/build.xml b/nashorn/make/build.xml index 732ac5fa0c2..8bdaf6071f3 100644 --- a/nashorn/make/build.xml +++ b/nashorn/make/build.xml @@ -209,7 +209,7 @@ - diff --git a/nashorn/make/nbproject/ide-targets.xml b/nashorn/make/nbproject/ide-targets.xml index d1e8135f101..7237f6d4120 100644 --- a/nashorn/make/nbproject/ide-targets.xml +++ b/nashorn/make/nbproject/ide-targets.xml @@ -32,9 +32,8 @@ - + - diff --git a/nashorn/make/nbproject/project.xml b/nashorn/make/nbproject/project.xml index 2fcc644292c..31e29ccf26d 100644 --- a/nashorn/make/nbproject/project.xml +++ b/nashorn/make/nbproject/project.xml @@ -37,10 +37,6 @@ . UTF-8 - - - ../src - ../test/src @@ -49,24 +45,28 @@ ../buildtools/nasgen/src + + + ../src/jdk.scripting.nashorn/share/classes + java ../test/src UTF-8 - - - java - ../src - UTF-8 - java ../buildtools/nasgen/src UTF-8 + + + java + ../src/jdk.scripting.nashorn/share/classes + UTF-8 + @@ -131,14 +131,14 @@ ../test/src - - - ../src - ../buildtools/nasgen/src + + + ../src/jdk.scripting.nashorn/share/classes + build.xml @@ -159,11 +159,7 @@ ../test/src - ../test/lib/testng.jar:../build/classes:../src - 1.7 - - - ../src + ../test/lib/testng.jar:../build/classes:../src/jdk.scripting.nashorn/share/classes 1.7 @@ -171,6 +167,10 @@ ../build/classes:../src 1.7 + + ../src/jdk.scripting.nashorn/share/classes + 1.7 + diff --git a/nashorn/make/project.properties b/nashorn/make/project.properties index 7180163a67e..a6a0b54a44b 100644 --- a/nashorn/make/project.properties +++ b/nashorn/make/project.properties @@ -24,7 +24,7 @@ application.title=nashorn # location of JDK embedded ASM sources -jdk.asm.src.dir=../jdk/src/share/classes/jdk/internal/org/objectweb/asm +jdk.asm.src.dir=../jdk/src/java.base/share/classes/jdk/internal/org/objectweb/asm # source and target levels build.compiler=modern diff --git a/nashorn/samples/browser_dom.js b/nashorn/samples/browser_dom.js index 94324c7ad75..789801fc3f9 100644 --- a/nashorn/samples/browser_dom.js +++ b/nashorn/samples/browser_dom.js @@ -1,4 +1,4 @@ -#// Usage: jjs -fx browser.js +#// Usage: jjs -fx browser_dom.js /* * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. @@ -32,7 +32,7 @@ */ if (!$OPTIONS._fx) { - print("Usage: jjs -fx browser.js"); + print("Usage: jjs -fx browser_dom.js"); exit(1); } @@ -40,7 +40,6 @@ if (!$OPTIONS._fx) { var ChangeListener = Java.type("javafx.beans.value.ChangeListener"); var Scene = Java.type("javafx.scene.Scene"); var WebView = Java.type("javafx.scene.web.WebView"); -var EventListener = Java.type("org.w3c.dom.events.EventListener"); // JavaFX start method function start(stage) { @@ -74,10 +73,10 @@ EOF, "text/html"); var btn = document.createElement("button"); var n = 0; // attach a button handler - nashorn function! - btn.onclick = new EventListener(function() { + btn.onclick = function() { n++; print("You clicked " + n + " time(s)"); print("you clicked OK " + wv.engine.executeScript("okCount")); - }); + }; // attach text to button var t = document.createTextNode("Click Me!"); btn.appendChild(t); diff --git a/nashorn/samples/time_color.fx b/nashorn/samples/time_color.fx new file mode 100644 index 00000000000..f4b1155d6e6 --- /dev/null +++ b/nashorn/samples/time_color.fx @@ -0,0 +1,89 @@ +#// Usage: jjs -fx time_color.js [-- true/false] + +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Oracle nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// A simple javafx program that changes background color +// of scene based on current time value (once per sec). +// inspired by http://whatcolourisit.scn9a.org/ + +if (!$OPTIONS._fx) { + print("Usage: jjs -fx time_color.js"); + print(" jjs -fx time_color.js -- true"); + exit(1); +} + +// JavaFX classes used +var Color = Java.type("javafx.scene.paint.Color"); +var Group = Java.type("javafx.scene.Group"); +var Label = Java.type("javafx.scene.control.Label"); +var Platform = Java.type("javafx.application.Platform"); +var Scene = Java.type("javafx.scene.Scene"); +var Timer = Java.type("java.util.Timer"); + +// execute function periodically once per given time in millisec +function setInterval(func, ms) { + // New timer, run as daemon so the application can quit + var timer = new Timer("setInterval", true); + timer.schedule(function() Platform.runLater(func), ms, ms); + return timer; +} + +// do you want to flip hour/min/sec for RGB? +var flip = arguments.length > 0? "true".equals(arguments[0]) : false; + +// JavaFX start method +function start(stage) { + start.title = "Time Color"; + var root = new Group(); + var label = new Label("time"); + label.textFill = Color.WHITE; + root.children.add(label); + stage.scene = new Scene(root, 700, 500); + + setInterval(function() { + var d = new Date(); + var hours = d.getHours(); + var mins = d.getMinutes(); + var secs = d.getSeconds(); + + if (hours < 10) hours = "0" + hours; + if (mins < 10) mins = "0" + mins; + if (secs < 10) secs = "0" + secs; + + var hex = flip? + "#" + secs + mins + hours : "#" + hours + mins + secs; + label.text = "Color: " + hex; + stage.scene.fill = Color.web(hex); + }, 1000); + + stage.show(); +} diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/LocalVariableTypesCalculator.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/LocalVariableTypesCalculator.java index ac3c29349b0..28cc55104b1 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/LocalVariableTypesCalculator.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/LocalVariableTypesCalculator.java @@ -40,21 +40,22 @@ import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; -import java.util.function.Function; import jdk.nashorn.internal.codegen.types.Type; import jdk.nashorn.internal.ir.AccessNode; -import jdk.nashorn.internal.ir.BaseNode; import jdk.nashorn.internal.ir.BinaryNode; import jdk.nashorn.internal.ir.Block; import jdk.nashorn.internal.ir.BreakNode; import jdk.nashorn.internal.ir.BreakableNode; +import jdk.nashorn.internal.ir.CallNode; import jdk.nashorn.internal.ir.CaseNode; import jdk.nashorn.internal.ir.CatchNode; import jdk.nashorn.internal.ir.ContinueNode; import jdk.nashorn.internal.ir.Expression; +import jdk.nashorn.internal.ir.ExpressionStatement; import jdk.nashorn.internal.ir.ForNode; import jdk.nashorn.internal.ir.FunctionNode; import jdk.nashorn.internal.ir.FunctionNode.CompilationState; +import jdk.nashorn.internal.ir.GetSplitState; import jdk.nashorn.internal.ir.IdentNode; import jdk.nashorn.internal.ir.IfNode; import jdk.nashorn.internal.ir.IndexNode; @@ -65,9 +66,11 @@ import jdk.nashorn.internal.ir.LabelNode; import jdk.nashorn.internal.ir.LexicalContext; import jdk.nashorn.internal.ir.LexicalContextNode; import jdk.nashorn.internal.ir.LiteralNode; +import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode; import jdk.nashorn.internal.ir.LocalVariableConversion; import jdk.nashorn.internal.ir.LoopNode; import jdk.nashorn.internal.ir.Node; +import jdk.nashorn.internal.ir.ObjectNode; import jdk.nashorn.internal.ir.PropertyNode; import jdk.nashorn.internal.ir.ReturnNode; import jdk.nashorn.internal.ir.RuntimeNode; @@ -82,6 +85,7 @@ import jdk.nashorn.internal.ir.TryNode; import jdk.nashorn.internal.ir.UnaryNode; import jdk.nashorn.internal.ir.VarNode; import jdk.nashorn.internal.ir.WhileNode; +import jdk.nashorn.internal.ir.WithNode; import jdk.nashorn.internal.ir.visitor.NodeVisitor; import jdk.nashorn.internal.parser.TokenType; @@ -131,8 +135,44 @@ final class LocalVariableTypesCalculator extends NodeVisitor{ OBJECT(Type.OBJECT); private final Type type; + private final TypeHolderExpression typeExpression; + private LvarType(final Type type) { this.type = type; + this.typeExpression = new TypeHolderExpression(type); + } + } + + /** + * A bogus Expression subclass that only reports its type. Used to interrogate BinaryNode and UnaryNode about their + * types by creating temporary copies of them and replacing their operands with instances of these. An alternative + * solution would be to add BinaryNode.getType(Type lhsType, Type rhsType) and UnaryNode.getType(Type exprType) + * methods. For the time being though, this is easier to implement and is in fact fairly clean. It does result in + * generation of higher number of temporary short lived nodes, though. + */ + private static class TypeHolderExpression extends Expression { + private static final long serialVersionUID = 1L; + + private final Type type; + + TypeHolderExpression(final Type type) { + super(0L, 0, 0); + this.type = type; + } + + @Override + public Node accept(final NodeVisitor visitor) { + throw new AssertionError(); + } + + @Override + public Type getType() { + return type; + } + + @Override + public void toString(final StringBuilder sb, final boolean printType) { + throw new AssertionError(); } } @@ -359,6 +399,8 @@ final class LocalVariableTypesCalculator extends NodeVisitor{ // allocates a new map. Immutability of maps allows for cheap snapshots by just keeping the reference to the current // value. private Map localVariableTypes = new IdentityHashMap<>(); + // Stack for evaluated expression types. + private final Deque typeStack = new ArrayDeque<>(); // Whether the current point in the AST is reachable code private boolean reachable = true; @@ -375,8 +417,6 @@ final class LocalVariableTypesCalculator extends NodeVisitor{ private final Map identifierLvarTypes = new IdentityHashMap<>(); private final Map symbolConversions = new IdentityHashMap<>(); - private SymbolToType symbolToType = new SymbolToType(); - // Stack of open labels for starts of catch blocks, one for every currently traversed try block; for inserting // control flow edges to them. Note that we currently don't insert actual control flow edges, but instead edges that // help us with type calculations. This means that some operations that can result in an exception being thrown @@ -400,62 +440,56 @@ final class LocalVariableTypesCalculator extends NodeVisitor{ private void doesNotContinueSequentially() { reachable = false; localVariableTypes = Collections.emptyMap(); + assertTypeStackIsEmpty(); } + private boolean pushExpressionType(final Expression expr) { + typeStack.push(toLvarType(expr.getType())); + return false; + } + + @Override + public boolean enterAccessNode(final AccessNode accessNode) { + visitExpression(accessNode.getBase()); + return pushExpressionType(accessNode); + } @Override public boolean enterBinaryNode(final BinaryNode binaryNode) { // NOTE: regardless of operator's lexical associativity, lhs is always evaluated first. final Expression lhs = binaryNode.lhs(); - final boolean isAssignment = binaryNode.isAssignment(); - LvarType lhsTypeOnLoad = null; - if(isAssignment) { - if(lhs instanceof BaseNode) { - ((BaseNode)lhs).getBase().accept(this); - if(lhs instanceof IndexNode) { - ((IndexNode)lhs).getIndex().accept(this); - } else { - assert lhs instanceof AccessNode; - } - } else { - assert lhs instanceof IdentNode; - if(binaryNode.isSelfModifying()) { - final IdentNode ident = ((IdentNode)lhs); - ident.accept(this); - // Self-assignment can cause a change in the type of the variable. For purposes of evaluating - // the type of the operation, we must use its type as it was when it was loaded. If we didn't - // do this, some awkward expressions would end up being calculated incorrectly, e.g. - // "var x; x += x = 0;". In this case we have undefined+int so the result type is double (NaN). - // However, if we used the type of "x" on LHS after we evaluated RHS, we'd see int+int, so the - // result type would be either optimistic int or pessimistic long, which would be wrong. - lhsTypeOnLoad = getLocalVariableTypeIfBytecode(ident.getSymbol()); - } - } + final LvarType lhsType; + if (!(lhs instanceof IdentNode && binaryNode.tokenType() == TokenType.ASSIGN)) { + lhsType = visitExpression(lhs); } else { - lhs.accept(this); + // Can't visit IdentNode on LHS of a simple assignment, as visits imply use, and this is def. + // The type is irrelevant, as only RHS is used to determine the type anyway. + lhsType = LvarType.UNDEFINED; } final boolean isLogical = binaryNode.isLogical(); - assert !(isAssignment && isLogical); // there are no logical assignment operators in JS final Label joinLabel = isLogical ? new Label("") : null; if(isLogical) { jumpToLabel((JoinPredecessor)lhs, joinLabel); } final Expression rhs = binaryNode.rhs(); - rhs.accept(this); + final LvarType rhsType = visitExpression(rhs); if(isLogical) { jumpToLabel((JoinPredecessor)rhs, joinLabel); } joinOnLabel(joinLabel); - if(isAssignment && lhs instanceof IdentNode) { + final LvarType type = toLvarType(binaryNode.setOperands(lhsType.typeExpression, rhsType.typeExpression).getType()); + + if(binaryNode.isAssignment() && lhs instanceof IdentNode) { if(binaryNode.isSelfModifying()) { - onSelfAssignment((IdentNode)lhs, binaryNode, lhsTypeOnLoad); + onSelfAssignment((IdentNode)lhs, type); } else { - onAssignment((IdentNode)lhs, rhs); + onAssignment((IdentNode)lhs, type); } } + typeStack.push(type); return false; } @@ -474,6 +508,17 @@ final class LocalVariableTypesCalculator extends NodeVisitor{ return enterJumpStatement(breakNode); } + @Override + public boolean enterCallNode(final CallNode callNode) { + visitExpression(callNode.getFunction()); + visitExpressions(callNode.getArgs()); + final CallNode.EvalArgs evalArgs = callNode.getEvalArgs(); + if (evalArgs != null) { + visitExpressions(evalArgs.getArgs()); + } + return pushExpressionType(callNode); + } + @Override public boolean enterContinueNode(final ContinueNode continueNode) { return enterJumpStatement(continueNode); @@ -483,6 +528,7 @@ final class LocalVariableTypesCalculator extends NodeVisitor{ if(!reachable) { return false; } + assertTypeStackIsEmpty(); final BreakableNode target = jump.getTarget(lc); jumpToLabel(jump, jump.getTargetLabel(target), getBreakTargetTypes(target)); doesNotContinueSequentially(); @@ -495,6 +541,7 @@ final class LocalVariableTypesCalculator extends NodeVisitor{ } private void enterDoWhileLoop(final WhileNode loopNode) { + assertTypeStackIsEmpty(); final JoinPredecessorExpression test = loopNode.getTest(); final Block body = loopNode.getBody(); final Label continueLabel = loopNode.getContinueLabel(); @@ -512,7 +559,7 @@ final class LocalVariableTypesCalculator extends NodeVisitor{ if(!reachable) { break; } - test.accept(this); + visitExpressionOnEmptyStack(test); jumpToLabel(test, breakLabel); if(isAlwaysFalse(test)) { break; @@ -534,6 +581,45 @@ final class LocalVariableTypesCalculator extends NodeVisitor{ leaveBreakable(loopNode); } + @Override + public boolean enterExpressionStatement(final ExpressionStatement expressionStatement) { + if (reachable) { + visitExpressionOnEmptyStack(expressionStatement.getExpression()); + } + return false; + } + + private void assertTypeStackIsEmpty() { + assert typeStack.isEmpty(); + } + + @Override + protected Node leaveDefault(final Node node) { + assert !(node instanceof Expression); // All expressions were handled + assert !(node instanceof Statement) || typeStack.isEmpty(); // No statements leave with a non-empty stack + return node; + } + + private LvarType visitExpressionOnEmptyStack(final Expression expr) { + assertTypeStackIsEmpty(); + return visitExpression(expr); + } + + private LvarType visitExpression(final Expression expr) { + final int stackSize = typeStack.size(); + expr.accept(this); + assert typeStack.size() == stackSize + 1; + return typeStack.pop(); + } + + private void visitExpressions(final List exprs) { + for(final Expression expr: exprs) { + if (expr != null) { + visitExpression(expr); + } + } + } + @Override public boolean enterForNode(final ForNode forNode) { if(!reachable) { @@ -543,7 +629,7 @@ final class LocalVariableTypesCalculator extends NodeVisitor{ final Expression init = forNode.getInit(); if(forNode.isForIn()) { final JoinPredecessorExpression iterable = forNode.getModify(); - iterable.accept(this); + visitExpression(iterable); enterTestFirstLoop(forNode, null, init, // If we're iterating over property names, and we can discern from the runtime environment // of the compilation that the object being iterated over must use strings for property @@ -552,16 +638,18 @@ final class LocalVariableTypesCalculator extends NodeVisitor{ !compiler.useOptimisticTypes() || (!forNode.isForEach() && compiler.hasStringPropertyIterator(iterable.getExpression()))); } else { if(init != null) { - init.accept(this); + visitExpressionOnEmptyStack(init); } enterTestFirstLoop(forNode, forNode.getModify(), null, false); } + assertTypeStackIsEmpty(); return false; } @Override public boolean enterFunctionNode(final FunctionNode functionNode) { if(alreadyEnteredTopLevelFunction) { + typeStack.push(LvarType.OBJECT); return false; } int pos = 0; @@ -602,12 +690,21 @@ final class LocalVariableTypesCalculator extends NodeVisitor{ return true; } + @Override + public boolean enterGetSplitState(final GetSplitState getSplitState) { + return pushExpressionType(getSplitState); + } + @Override public boolean enterIdentNode(final IdentNode identNode) { final Symbol symbol = identNode.getSymbol(); if(symbol.isBytecodeLocal()) { symbolIsUsed(symbol); - setIdentifierLvarType(identNode, getLocalVariableType(symbol)); + final LvarType type = getLocalVariableType(symbol); + setIdentifierLvarType(identNode, type); + typeStack.push(type); + } else { + pushExpressionType(identNode); } return false; } @@ -622,11 +719,12 @@ final class LocalVariableTypesCalculator extends NodeVisitor{ final Block pass = ifNode.getPass(); final Block fail = ifNode.getFail(); - test.accept(this); + visitExpressionOnEmptyStack(test); final Map afterTestLvarTypes = localVariableTypes; if(!isAlwaysFalse(test)) { pass.accept(this); + assertTypeStackIsEmpty(); } final Map passLvarTypes = localVariableTypes; final boolean reachableFromPass = reachable; @@ -635,6 +733,7 @@ final class LocalVariableTypesCalculator extends NodeVisitor{ localVariableTypes = afterTestLvarTypes; if(!isAlwaysTrue(test) && fail != null) { fail.accept(this); + assertTypeStackIsEmpty(); final boolean reachableFromFail = reachable; reachable |= reachableFromPass; if(!reachable) { @@ -667,14 +766,53 @@ final class LocalVariableTypesCalculator extends NodeVisitor{ } @Override - public boolean enterPropertyNode(final PropertyNode propertyNode) { - // Avoid falsely adding property keys to the control flow graph - if(propertyNode.getValue() != null) { - propertyNode.getValue().accept(this); + public boolean enterIndexNode(final IndexNode indexNode) { + visitExpression(indexNode.getBase()); + visitExpression(indexNode.getIndex()); + return pushExpressionType(indexNode); + } + + @Override + public boolean enterJoinPredecessorExpression(final JoinPredecessorExpression joinExpr) { + final Expression expr = joinExpr.getExpression(); + if (expr != null) { + expr.accept(this); + } else { + typeStack.push(LvarType.UNDEFINED); } return false; } + @Override + public boolean enterLiteralNode(final LiteralNode literalNode) { + if (literalNode instanceof ArrayLiteralNode) { + final List expressions = ((ArrayLiteralNode)literalNode).getElementExpressions(); + if (expressions != null) { + visitExpressions(expressions); + } + } + pushExpressionType(literalNode); + return false; + } + + @Override + public boolean enterObjectNode(final ObjectNode objectNode) { + for(final PropertyNode propertyNode: objectNode.getElements()) { + // Avoid falsely adding property keys to the control flow graph + final Expression value = propertyNode.getValue(); + if (value != null) { + visitExpression(value); + } + } + return pushExpressionType(objectNode); + } + + @Override + public boolean enterPropertyNode(final PropertyNode propertyNode) { + // Property nodes are only accessible through object literals, and we handled that case above + throw new AssertionError(); + } + @Override public boolean enterReturnNode(final ReturnNode returnNode) { if(!reachable) { @@ -684,9 +822,9 @@ final class LocalVariableTypesCalculator extends NodeVisitor{ final Expression returnExpr = returnNode.getExpression(); final Type returnExprType; if(returnExpr != null) { - returnExpr.accept(this); - returnExprType = getType(returnExpr); + returnExprType = visitExpressionOnEmptyStack(returnExpr).type; } else { + assertTypeStackIsEmpty(); returnExprType = Type.UNDEFINED; } returnType = Type.widestReturnType(returnType, returnExprType); @@ -694,6 +832,12 @@ final class LocalVariableTypesCalculator extends NodeVisitor{ return false; } + @Override + public boolean enterRuntimeNode(final RuntimeNode runtimeNode) { + visitExpressions(runtimeNode.getArgs()); + return pushExpressionType(runtimeNode); + } + @Override public boolean enterSplitReturn(final SplitReturn splitReturn) { doesNotContinueSequentially(); @@ -706,8 +850,7 @@ final class LocalVariableTypesCalculator extends NodeVisitor{ return false; } - final Expression expr = switchNode.getExpression(); - expr.accept(this); + visitExpressionOnEmptyStack(switchNode.getExpression()); final List cases = switchNode.getCases(); if(cases.isEmpty()) { @@ -724,7 +867,7 @@ final class LocalVariableTypesCalculator extends NodeVisitor{ for(final CaseNode caseNode: cases) { final Expression test = caseNode.getTest(); if(!isInteger && test != null) { - test.accept(this); + visitExpressionOnEmptyStack(test); if(!tagUsed) { symbolIsUsed(switchNode.getTag(), LvarType.OBJECT); tagUsed = true; @@ -769,29 +912,42 @@ final class LocalVariableTypesCalculator extends NodeVisitor{ final Expression trueExpr = ternaryNode.getTrueExpression(); final Expression falseExpr = ternaryNode.getFalseExpression(); - test.accept(this); + visitExpression(test); final Map testExitLvarTypes = localVariableTypes; + final LvarType trueType; if(!isAlwaysFalse(test)) { - trueExpr.accept(this); + trueType = visitExpression(trueExpr); + } else { + trueType = null; } final Map trueExitLvarTypes = localVariableTypes; localVariableTypes = testExitLvarTypes; + final LvarType falseType; if(!isAlwaysTrue(test)) { - falseExpr.accept(this); + falseType = visitExpression(falseExpr); + } else { + falseType = null; } final Map falseExitLvarTypes = localVariableTypes; localVariableTypes = getUnionTypes(trueExitLvarTypes, falseExitLvarTypes); setConversion((JoinPredecessor)trueExpr, trueExitLvarTypes, localVariableTypes); setConversion((JoinPredecessor)falseExpr, falseExitLvarTypes, localVariableTypes); + + typeStack.push(trueType != null ? falseType != null ? widestLvarType(trueType, falseType) : trueType : assertNotNull(falseType)); return false; } + private static T assertNotNull(final T t) { + assert t != null; + return t; + } + private void enterTestFirstLoop(final LoopNode loopNode, final JoinPredecessorExpression modify, final Expression iteratorValues, final boolean iteratorValuesAreObject) { final JoinPredecessorExpression test = loopNode.getTest(); if(isAlwaysFalse(test)) { - test.accept(this); + visitExpressionOnEmptyStack(test); return; } @@ -804,7 +960,7 @@ final class LocalVariableTypesCalculator extends NodeVisitor{ jumpToLabel(loopNode, repeatLabel, beforeLoopTypes); final Map beforeRepeatTypes = localVariableTypes; if(test != null) { - test.accept(this); + visitExpressionOnEmptyStack(test); } if(!isAlwaysTrue(test)) { jumpToLabel(test, breakLabel); @@ -827,7 +983,7 @@ final class LocalVariableTypesCalculator extends NodeVisitor{ break; } if(modify != null) { - modify.accept(this); + visitExpressionOnEmptyStack(modify); jumpToLabel(modify, repeatLabel); joinOnLabel(repeatLabel); } @@ -853,7 +1009,7 @@ final class LocalVariableTypesCalculator extends NodeVisitor{ return false; } - throwNode.getExpression().accept(this); + visitExpressionOnEmptyStack(throwNode.getExpression()); jumpToCatchBlock(throwNode); doesNotContinueSequentially(); return false; @@ -892,7 +1048,7 @@ final class LocalVariableTypesCalculator extends NodeVisitor{ onAssignment(exception, LvarType.OBJECT); final Expression condition = catchNode.getExceptionCondition(); if(condition != null) { - condition.accept(this); + visitExpression(condition); } final Map afterConditionTypes = localVariableTypes; final Block catchBody = catchNode.getBody(); @@ -927,14 +1083,11 @@ final class LocalVariableTypesCalculator extends NodeVisitor{ @Override public boolean enterUnaryNode(final UnaryNode unaryNode) { final Expression expr = unaryNode.getExpression(); - expr.accept(this); - - if(unaryNode.isSelfModifying()) { - if(expr instanceof IdentNode) { - final IdentNode ident = (IdentNode)expr; - onSelfAssignment(ident, unaryNode, getLocalVariableTypeIfBytecode(ident.getSymbol())); - } + final LvarType unaryType = toLvarType(unaryNode.setExpression(visitExpression(expr).typeExpression).getType()); + if(unaryNode.isSelfModifying() && expr instanceof IdentNode) { + onSelfAssignment((IdentNode)expr, unaryType); } + typeStack.push(unaryType); return false; } @@ -945,8 +1098,7 @@ final class LocalVariableTypesCalculator extends NodeVisitor{ } final Expression init = varNode.getInit(); if(init != null) { - init.accept(this); - onAssignment(varNode.getName(), init); + onAssignment(varNode.getName(), visitExpression(init)); } return false; } @@ -964,6 +1116,15 @@ final class LocalVariableTypesCalculator extends NodeVisitor{ return false; } + @Override + public boolean enterWithNode(final WithNode withNode) { + if (reachable) { + visitExpression(withNode.getExpression()); + withNode.getBody().accept(this); + } + return false; + }; + private Map getBreakTargetTypes(final BreakableNode target) { // Remove symbols defined in the the blocks that are being broken out of. Map types = localVariableTypes; @@ -1001,18 +1162,6 @@ final class LocalVariableTypesCalculator extends NodeVisitor{ return type; } - /** - * Gets the type for a local variable if it is a bytecode local, otherwise null. Can be used in circumstances where - * the type is irrelevant if the symbol is not a bytecode local. Note that for bytecode locals, it delegates to - * {@link #getLocalVariableType(Symbol)}, so it will still assert that the type for such variable is already - * defined (that is, not null). - * @param symbol the symbol representing the variable. - * @return the current variable type, if it is a bytecode local, otherwise null. - */ - private LvarType getLocalVariableTypeIfBytecode(final Symbol symbol) { - return symbol.isBytecodeLocal() ? getLocalVariableType(symbol) : null; - } - /** * Gets the type for a variable represented by a symbol, or null if the type is not know. This is the least strict * of all local variable type getters, and as such its use is discouraged except in initialization scenarios (where @@ -1154,6 +1303,7 @@ final class LocalVariableTypesCalculator extends NodeVisitor{ */ private void leaveBreakable(final BreakableNode breakable) { joinOnLabel(breakable.getBreakLabel()); + assertTypeStackIsEmpty(); } @Override @@ -1329,10 +1479,6 @@ final class LocalVariableTypesCalculator extends NodeVisitor{ return conv == null || !conv.isLive(); } - private void onAssignment(final IdentNode identNode, final Expression rhs) { - onAssignment(identNode, toLvarType(getType(rhs))); - } - private void onAssignment(final IdentNode identNode, final LvarType type) { final Symbol symbol = identNode.getSymbol(); assert symbol != null : identNode.getName(); @@ -1400,13 +1546,12 @@ final class LocalVariableTypesCalculator extends NodeVisitor{ jumpToCatchBlock(identNode); } - private void onSelfAssignment(final IdentNode identNode, final Expression assignment, final LvarType typeOnLoad) { + private void onSelfAssignment(final IdentNode identNode, final LvarType type) { final Symbol symbol = identNode.getSymbol(); assert symbol != null : identNode.getName(); if(!symbol.isBytecodeLocal()) { return; } - final LvarType type = toLvarType(getType(assignment, symbol, typeOnLoad.type)); // Self-assignment never produce either a boolean or undefined assert type != null && type != LvarType.UNDEFINED && type != LvarType.BOOLEAN; setType(symbol, type); @@ -1466,7 +1611,6 @@ final class LocalVariableTypesCalculator extends NodeVisitor{ * @param symbol the symbol representing the variable * @param type the type */ - @SuppressWarnings("unused") private void setType(final Symbol symbol, final LvarType type) { if(getLocalVariableTypeOrNull(symbol) == type) { return; @@ -1486,77 +1630,4 @@ final class LocalVariableTypesCalculator extends NodeVisitor{ private void symbolIsUsed(final Symbol symbol) { symbolIsUsed(symbol, getLocalVariableType(symbol)); } - - /** - * Gets the type of the expression, dependent on the current types of the local variables. - * - * @param expr the expression - * @return the current type of the expression dependent on the current types of the local variables. - */ - private Type getType(final Expression expr) { - return expr.getType(getSymbolToType()); - } - - /** - * Returns a function object from symbols to their types, used by the expressions to evaluate their type. - * {@link BinaryNode} specifically uses identity of the function to cache type calculations. This method makes - * sure to return the same function object while the local variable types don't change, and create a new function - * object if the local variable types have been changed. - * @return a function object representing a mapping from symbols to their types. - */ - private Function getSymbolToType() { - if(symbolToType.isStale()) { - symbolToType = new SymbolToType(); - } - return symbolToType; - } - - private class SymbolToType implements Function { - private final Object boundTypes = localVariableTypes; - @Override - public Type apply(final Symbol t) { - return getLocalVariableType(t).type; - } - - boolean isStale() { - return boundTypes != localVariableTypes; - } - } - - /** - * Gets the type of the expression, dependent on the current types of the local variables and a single overridden - * symbol type. Used by type calculation on compound operators to ensure the type of the LHS at the time it was - * loaded (which can potentially be different after RHS evaluation, e.g. "var x; x += x = 0;") is preserved for - * the calculation. - * - * @param expr the expression - * @param overriddenSymbol the overridden symbol - * @param overriddenType the overridden type - * @return the current type of the expression dependent on the current types of the local variables and the single - * potentially overridden type. - */ - private Type getType(final Expression expr, final Symbol overriddenSymbol, final Type overriddenType) { - return expr.getType(getSymbolToType(overriddenSymbol, overriddenType)); - } - - private Function getSymbolToType(final Symbol overriddenSymbol, final Type overriddenType) { - return getLocalVariableType(overriddenSymbol).type == overriddenType ? getSymbolToType() : - new SymbolToTypeOverride(overriddenSymbol, overriddenType); - } - - private class SymbolToTypeOverride implements Function { - private final Function originalSymbolToType = getSymbolToType(); - private final Symbol overriddenSymbol; - private final Type overriddenType; - - SymbolToTypeOverride(final Symbol overriddenSymbol, final Type overriddenType) { - this.overriddenSymbol = overriddenSymbol; - this.overriddenType = overriddenType; - } - - @Override - public Type apply(final Symbol symbol) { - return symbol == overriddenSymbol ? overriddenType : originalSymbolToType.apply(symbol); - } - } } diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/OptimisticTypesPersistence.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/OptimisticTypesPersistence.java index 5cbed1bece2..98a0c15be72 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/OptimisticTypesPersistence.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/OptimisticTypesPersistence.java @@ -67,7 +67,7 @@ import jdk.nashorn.internal.runtime.logging.DebugLogger; import jdk.nashorn.internal.runtime.options.Options; /** - * Static utility that encapsulates persistence of type information for functions compiled with optimistic + *

Static utility that encapsulates persistence of type information for functions compiled with optimistic * typing. With this feature enabled, when a JavaScript function is recompiled because it gets deoptimized, * the type information for deoptimization is stored in a cache file. If the same function is compiled in a * subsequent JVM invocation, the type information is used for initial compilation, thus allowing the system @@ -83,6 +83,7 @@ import jdk.nashorn.internal.runtime.options.Options; * {@code nashorn.typeInfo.cleanupDelaySeconds} system property. You can also specify the word * {@code unlimited} as the value for {@code nashorn.typeInfo.maxFiles} in which case the type info cache is * allowed to grow without limits. + *

*/ public final class OptimisticTypesPersistence { // Default is 0, for disabling the feature when not specified. A reasonable default when enabled is diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/BaseNode.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/BaseNode.java index 35479a7a58b..9c4156e8993 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/BaseNode.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/BaseNode.java @@ -27,7 +27,6 @@ package jdk.nashorn.internal.ir; import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_PROGRAM_POINT; -import java.util.function.Function; import jdk.nashorn.internal.codegen.types.Type; import jdk.nashorn.internal.ir.annotations.Immutable; @@ -98,7 +97,7 @@ public abstract class BaseNode extends Expression implements FunctionCall, Optim } @Override - public Type getType(final Function localVariableTypes) { + public Type getType() { return type == null ? getMostPessimisticType() : type; } diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/BinaryNode.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/BinaryNode.java index f625fe1a691..24be9c2d814 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/BinaryNode.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/BinaryNode.java @@ -31,7 +31,6 @@ import java.util.Arrays; import java.util.Collections; import java.util.HashSet; import java.util.Set; -import java.util.function.Function; import jdk.nashorn.internal.codegen.types.Type; import jdk.nashorn.internal.ir.annotations.Ignore; import jdk.nashorn.internal.ir.annotations.Immutable; @@ -57,9 +56,7 @@ public final class BinaryNode extends Expression implements Assignment CAN_OVERFLOW = @@ -143,24 +140,6 @@ public final class BinaryNode extends Expression implements Assignment UNKNOWN_LOCALS = new Function() { - @Override - public Type apply(final Symbol t) { - return null; - } - }; - - /** - * Return the widest possible type for this operation. This is used for compile time - * static type inference - * - * @return Type - */ - @Override - public Type getWidestOperationType() { - return getWidestOperationType(UNKNOWN_LOCALS); - } - /** * Return the widest possible operand type for this operation. * @@ -181,14 +160,15 @@ public final class BinaryNode extends Expression implements Assignment localVariableTypes) { + @Override + public Type getWidestOperationType() { switch (tokenType()) { case ADD: case ASSIGN_ADD: { // Compare this logic to decideType(Type, Type); it's similar, but it handles the optimistic type // calculation case while this handles the conservative case. - final Type lhsType = lhs.getType(localVariableTypes); - final Type rhsType = rhs.getType(localVariableTypes); + final Type lhsType = lhs.getType(); + final Type rhsType = rhs.getType(); if(lhsType == Type.BOOLEAN && rhsType == Type.BOOLEAN) { // Will always fit in an int, as the value range is [0, 1, 2]. If we didn't treat them specially here, // they'd end up being treated as generic INT operands and their sum would be conservatively considered @@ -238,8 +218,8 @@ public final class BinaryNode extends Expression implements Assignment localVariableTypes) { - if(localVariableTypes == cachedTypeFunction) { - return cachedType; + public Type getType() { + if (cachedType == null) { + cachedType = getTypeUncached(); } - cachedType = getTypeUncached(localVariableTypes); - cachedTypeFunction = localVariableTypes; return cachedType; } - private Type getTypeUncached(final Function localVariableTypes) { + private Type getTypeUncached() { if(type == OPTIMISTIC_UNDECIDED_TYPE) { - return decideType(lhs.getType(localVariableTypes), rhs.getType(localVariableTypes)); + return decideType(lhs.getType(), rhs.getType()); } - final Type widest = getWidestOperationType(localVariableTypes); + final Type widest = getWidestOperationType(); if(type == null) { return widest; } - return Type.narrowest(widest, Type.widest(type, Type.widest(lhs.getType(localVariableTypes), rhs.getType(localVariableTypes)))); + return Type.narrowest(widest, Type.widest(type, Type.widest(lhs.getType(), rhs.getType()))); } private static Type decideType(final Type lhsType, final Type rhsType) { diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/CallNode.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/CallNode.java index 72eab68b850..95a116652d3 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/CallNode.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/CallNode.java @@ -30,7 +30,6 @@ import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_ import java.io.Serializable; import java.util.Collections; import java.util.List; -import java.util.function.Function; import jdk.nashorn.internal.codegen.types.Type; import jdk.nashorn.internal.ir.annotations.Ignore; import jdk.nashorn.internal.ir.annotations.Immutable; @@ -154,7 +153,7 @@ public final class CallNode extends LexicalContextExpression implements Optimist } @Override - public Type getType(final Function localVariableTypes) { + public Type getType() { return optimisticType == null ? Type.OBJECT : optimisticType; } diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/Expression.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/Expression.java index 78523412e46..e62eb732d52 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/Expression.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/Expression.java @@ -25,7 +25,6 @@ package jdk.nashorn.internal.ir; -import java.util.function.Function; import jdk.nashorn.internal.codegen.types.Type; import jdk.nashorn.internal.runtime.UnwarrantedOptimismException; @@ -39,14 +38,7 @@ public abstract class Expression extends Node { static final String OPT_IDENTIFIER = "%"; - private static final Function UNKNOWN_LOCALS = new Function() { - @Override - public Type apply(final Symbol t) { - return null; - } - }; - - Expression(final long token, final int start, final int finish) { + protected Expression(final long token, final int start, final int finish) { super(token, start, finish); } @@ -63,18 +55,7 @@ public abstract class Expression extends Node { * * @return the type of the expression. */ - public final Type getType() { - return getType(UNKNOWN_LOCALS); - } - - /** - * Returns the type of the expression under the specified symbol-to-type mapping. By default delegates to - * {@link #getType()} but expressions whose type depends on their subexpressions' types and expressions whose type - * depends on symbol type ({@link IdentNode}) will have a special implementation. - * @param localVariableTypes a mapping from symbols to their types, used for type calculation. - * @return the type of the expression under the specified symbol-to-type mapping. - */ - public abstract Type getType(final Function localVariableTypes); + public abstract Type getType(); /** * Returns {@code true} if this expression depends exclusively on state that is constant diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/FunctionNode.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/FunctionNode.java index 383b9bb6427..783043f520f 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/FunctionNode.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/FunctionNode.java @@ -36,7 +36,6 @@ import java.util.Collections; import java.util.EnumSet; import java.util.Iterator; import java.util.List; -import java.util.function.Function; import jdk.nashorn.internal.AssertsEnabled; import jdk.nashorn.internal.codegen.CompileUnit; import jdk.nashorn.internal.codegen.Compiler; @@ -1101,7 +1100,7 @@ public final class FunctionNode extends LexicalContextExpression implements Flag } @Override - public Type getType(final Function localVariableTypes) { + public Type getType() { return FUNCTION_TYPE; } diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/GetSplitState.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/GetSplitState.java index bf4a4c01b8a..29c11b48eab 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/GetSplitState.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/GetSplitState.java @@ -25,7 +25,6 @@ package jdk.nashorn.internal.ir; -import java.util.function.Function; import jdk.nashorn.internal.codegen.CompilerConstants; import jdk.nashorn.internal.codegen.types.Type; import jdk.nashorn.internal.ir.visitor.NodeVisitor; @@ -47,7 +46,7 @@ public final class GetSplitState extends Expression { } @Override - public Type getType(final Function localVariableTypes) { + public Type getType() { return Type.INT; } diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/IdentNode.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/IdentNode.java index 7059734da1b..4570181af07 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/IdentNode.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/IdentNode.java @@ -30,7 +30,6 @@ import static jdk.nashorn.internal.codegen.CompilerConstants.__FILE__; import static jdk.nashorn.internal.codegen.CompilerConstants.__LINE__; import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_PROGRAM_POINT; -import java.util.function.Function; import jdk.nashorn.internal.codegen.types.Type; import jdk.nashorn.internal.ir.annotations.Immutable; import jdk.nashorn.internal.ir.visitor.NodeVisitor; @@ -118,14 +117,13 @@ public final class IdentNode extends Expression implements PropertyKey, Function } @Override - public Type getType(final Function localVariableTypes) { + public Type getType() { if(type != null) { return type; } else if(symbol != null && symbol.isScope()) { return Type.OBJECT; } - final Type symbolType = localVariableTypes.apply(symbol); - return symbolType == null ? Type.UNDEFINED : symbolType; + return Type.UNDEFINED; } /** diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/JoinPredecessorExpression.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/JoinPredecessorExpression.java index cfb0086b270..7f0d990dea8 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/JoinPredecessorExpression.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/JoinPredecessorExpression.java @@ -25,7 +25,6 @@ package jdk.nashorn.internal.ir; -import java.util.function.Function; import jdk.nashorn.internal.codegen.types.Type; import jdk.nashorn.internal.ir.visitor.NodeVisitor; @@ -71,8 +70,8 @@ public class JoinPredecessorExpression extends Expression implements JoinPredece } @Override - public Type getType(final Function localVariableTypes) { - return expression.getType(localVariableTypes); + public Type getType() { + return expression.getType(); } @Override diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/LiteralNode.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/LiteralNode.java index 6aee20cd7d7..f2a9003c39b 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/LiteralNode.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/LiteralNode.java @@ -29,7 +29,6 @@ import java.io.Serializable; import java.util.Arrays; import java.util.Collections; import java.util.List; -import java.util.function.Function; import jdk.nashorn.internal.codegen.CompileUnit; import jdk.nashorn.internal.codegen.types.ArrayType; import jdk.nashorn.internal.codegen.types.Type; @@ -109,7 +108,7 @@ public abstract class LiteralNode extends Expression implements PropertyKey { } @Override - public Type getType(final Function localVariableTypes) { + public Type getType() { return Type.typeFor(value.getClass()); } @@ -163,16 +162,6 @@ public abstract class LiteralNode extends Expression implements PropertyKey { return JSType.toNumber(value); } - /** - * Get the array value of the node - * - * @return the array value - */ - public Node[] getArray() { - assert false : "not an array node"; - return null; - } - /** * Fetch String value of node. * @@ -325,7 +314,7 @@ public abstract class LiteralNode extends Expression implements PropertyKey { } @Override - public Type getType(final Function localVariableTypes) { + public Type getType() { return Type.BOOLEAN; } @@ -389,7 +378,7 @@ public abstract class LiteralNode extends Expression implements PropertyKey { } @Override - public Type getType(final Function localVariableTypes) { + public Type getType() { return type; } @@ -519,7 +508,7 @@ public abstract class LiteralNode extends Expression implements PropertyKey { } @Override - public Type getType(final Function localVariableTypes) { + public Type getType() { return Type.OBJECT; } @@ -589,7 +578,7 @@ public abstract class LiteralNode extends Expression implements PropertyKey { } @Override - public Type getType(final Function localVariableTypes) { + public Type getType() { return Type.OBJECT; } @@ -840,9 +829,13 @@ public abstract class LiteralNode extends Expression implements PropertyKey { this.units = units; } - @Override - public Node[] getArray() { - return value; + /** + * Returns a list of array element expressions. Note that empty array elements manifest themselves as + * null. + * @return a list of array element expressions. + */ + public List getElementExpressions() { + return Collections.unmodifiableList(Arrays.asList(value)); } /** @@ -879,7 +872,7 @@ public abstract class LiteralNode extends Expression implements PropertyKey { } @Override - public Type getType(final Function localVariableTypes) { + public Type getType() { return Type.typeFor(NativeArray.class); } diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/ObjectNode.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/ObjectNode.java index d5bd78b57d2..31ddc1cd608 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/ObjectNode.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/ObjectNode.java @@ -27,7 +27,6 @@ package jdk.nashorn.internal.ir; import java.util.Collections; import java.util.List; -import java.util.function.Function; import jdk.nashorn.internal.codegen.types.Type; import jdk.nashorn.internal.ir.annotations.Immutable; import jdk.nashorn.internal.ir.visitor.NodeVisitor; @@ -69,7 +68,7 @@ public final class ObjectNode extends Expression { } @Override - public Type getType(final Function localVariableTypes) { + public Type getType() { return Type.OBJECT; } diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/RuntimeNode.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/RuntimeNode.java index 4eca8ff084b..0f0ea78b189 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/RuntimeNode.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/RuntimeNode.java @@ -30,7 +30,6 @@ import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_ import java.util.Arrays; import java.util.Collections; import java.util.List; -import java.util.function.Function; import jdk.nashorn.internal.codegen.types.Type; import jdk.nashorn.internal.ir.annotations.Immutable; import jdk.nashorn.internal.ir.visitor.NodeVisitor; @@ -460,7 +459,7 @@ public class RuntimeNode extends Expression implements Optimistic { * Return type for the ReferenceNode */ @Override - public Type getType(final Function localVariableTypes) { + public Type getType() { return request.getReturnType(); } diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/TernaryNode.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/TernaryNode.java index 913262d9a8c..e3bca0b980f 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/TernaryNode.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/TernaryNode.java @@ -25,7 +25,6 @@ package jdk.nashorn.internal.ir; -import java.util.function.Function; import jdk.nashorn.internal.codegen.types.Type; import jdk.nashorn.internal.ir.annotations.Immutable; import jdk.nashorn.internal.ir.visitor.NodeVisitor; @@ -122,8 +121,8 @@ public final class TernaryNode extends Expression { } @Override - public Type getType(final Function localVariableTypes) { - return Type.widestReturnType(getTrueExpression().getType(localVariableTypes), getFalseExpression().getType(localVariableTypes)); + public Type getType() { + return Type.widestReturnType(getTrueExpression().getType(), getFalseExpression().getType()); } diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/UnaryNode.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/UnaryNode.java index 2cee33b6c1c..2f7b268a4c5 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/UnaryNode.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/UnaryNode.java @@ -33,7 +33,6 @@ import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_ import java.util.Arrays; import java.util.Collections; import java.util.List; -import java.util.function.Function; import jdk.nashorn.internal.codegen.types.Type; import jdk.nashorn.internal.ir.annotations.Ignore; import jdk.nashorn.internal.ir.annotations.Immutable; @@ -123,23 +122,11 @@ public final class UnaryNode extends Expression implements Assignment UNKNOWN_LOCALS = new Function() { - @Override - public Type apply(final Symbol t) { - return null; - } - }; - - @Override public Type getWidestOperationType() { - return getWidestOperationType(UNKNOWN_LOCALS); - } - - private Type getWidestOperationType(final Function localVariableTypes) { switch (tokenType()) { case ADD: - final Type operandType = getExpression().getType(localVariableTypes); + final Type operandType = getExpression().getType(); if(operandType == Type.BOOLEAN) { return Type.INT; } else if(operandType.isObject()) { @@ -326,12 +313,12 @@ public final class UnaryNode extends Expression implements Assignment localVariableTypes) { - final Type widest = getWidestOperationType(localVariableTypes); + public Type getType() { + final Type widest = getWidestOperationType(); if(type == null) { return widest; } - return Type.narrowest(widest, Type.widest(type, expression.getType(localVariableTypes))); + return Type.narrowest(widest, Type.widest(type, expression.getType())); } @Override diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/debug/JSONWriter.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/debug/JSONWriter.java index e3916d694e6..9cee46ff8d2 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/debug/JSONWriter.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/debug/JSONWriter.java @@ -28,7 +28,6 @@ package jdk.nashorn.internal.ir.debug; import static jdk.nashorn.internal.runtime.Source.sourceFor; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; import jdk.nashorn.internal.ir.AccessNode; import jdk.nashorn.internal.ir.BinaryNode; @@ -553,8 +552,7 @@ public final class JSONWriter extends NodeVisitor { type("ArrayExpression"); comma(); - final Node[] value = literalNode.getArray(); - array("elements", Arrays.asList(value)); + array("elements", ((LiteralNode.ArrayLiteralNode)literalNode).getElementExpressions()); } else { type("Literal"); comma(); diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeArray.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeArray.java index 047d612ac54..0033ed71915 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeArray.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeArray.java @@ -275,7 +275,7 @@ public final class NativeArray extends ScriptObject implements OptimisticBuiltin final PropertyDescriptor newLenDesc = desc; // Step 3c and 3d - get new length and convert to long - final long newLen = NativeArray.validLength(newLenDesc.getValue(), true); + final long newLen = NativeArray.validLength(newLenDesc.getValue()); // Step 3e newLenDesc.setValue(newLen); @@ -348,8 +348,8 @@ public final class NativeArray extends ScriptObject implements OptimisticBuiltin final PropertyDescriptor oldLenDesc = (PropertyDescriptor) super.getOwnPropertyDescriptor("length"); // Step 2 - // get old length and convert to long - final long oldLen = NativeArray.validLength(oldLenDesc.getValue(), true); + // get old length and convert to long. Always a Long/Uint32 but we take the safe road. + final long oldLen = JSType.toUint32(oldLenDesc.getValue()); // Step 3 if ("length".equals(key)) { @@ -471,7 +471,7 @@ public final class NativeArray extends ScriptObject implements OptimisticBuiltin @Setter(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_CONFIGURABLE) public static void length(final Object self, final Object length) { if (isArray(self)) { - ((ScriptObject)self).setLength(validLength(length, true)); + ((ScriptObject)self).setLength(validLength(length)); } } @@ -495,18 +495,13 @@ public final class NativeArray extends ScriptObject implements OptimisticBuiltin length(self, length); // Same as instance setter but we can't make nasgen use the same method for prototype } - static long validLength(final Object length, final boolean reject) { + static long validLength(final Object length) { + // ES5 15.4.5.1, steps 3.c and 3.d require two ToNumber conversions here final double doubleLength = JSType.toNumber(length); - if (!Double.isNaN(doubleLength) && JSType.isRepresentableAsLong(doubleLength)) { - final long len = (long) doubleLength; - if (len >= 0 && len <= JSType.MAX_UINT) { - return len; - } - } - if (reject) { + if (doubleLength != JSType.toUint32(length)) { throw rangeError("inappropriate.array.length", ScriptRuntime.safeToString(length)); } - return -1; + return (long) doubleLength; } /** diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeRegExpExecResult.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeRegExpExecResult.java index 467399aeae2..0df0eca4a3c 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeRegExpExecResult.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeRegExpExecResult.java @@ -88,7 +88,7 @@ public final class NativeRegExpExecResult extends ScriptObject { @Setter(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_CONFIGURABLE) public static void length(final Object self, final Object length) { if (self instanceof ScriptObject) { - ((ScriptObject)self).setLength(NativeArray.validLength(length, true)); + ((ScriptObject)self).setLength(NativeArray.validLength(length)); } } } diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/CodeInstaller.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/CodeInstaller.java index e2b5afe8b3e..49b5b0e6b6f 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/CodeInstaller.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/CodeInstaller.java @@ -86,7 +86,7 @@ public interface CodeInstaller { * @param source the script source * @param mainClassName the main class name * @param classBytes map of class names to class bytes - * @param initializers compilation id -> FunctionInitializer map + * @param initializers compilation id -> FunctionInitializer map * @param constants constants array * @param compilationId compilation id */ diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/JSType.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/JSType.java index 7e54b1e2257..e2c93db4b47 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/JSType.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/JSType.java @@ -180,10 +180,10 @@ public enum JSType { /** Div exact wrapper for potentially integer division that turns into float point */ public static final Call DIV_EXACT_LONG = staticCall(JSTYPE_LOOKUP, JSType.class, "divExact", long.class, long.class, long.class, int.class); - /** Div zero wrapper for long division that handles (0/0) >>> 0 == 0 */ + /** Div zero wrapper for long division that handles (0/0) >>> 0 == 0 */ public static final Call DIV_ZERO_LONG = staticCall(JSTYPE_LOOKUP, JSType.class, "divZero", long.class, long.class, long.class); - /** Mod zero wrapper for long division that handles (0%0) >>> 0 == 0 */ + /** Mod zero wrapper for long division that handles (0%0) >>> 0 == 0 */ public static final Call REM_ZERO_LONG = staticCall(JSTYPE_LOOKUP, JSType.class, "remZero", long.class, long.class, long.class); /** Mod exact wrapper for potentially integer remainders that turns into float point */ diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/StoredScript.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/StoredScript.java index 14a0ced0c05..b36cec8b9d1 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/StoredScript.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/StoredScript.java @@ -58,7 +58,7 @@ public final class StoredScript implements Serializable { * @param compilationId compilation id * @param mainClassName main class name * @param classBytes map of class names to class bytes - * @param initializers initializer map, id -> FunctionInitializer + * @param initializers initializer map, id -> FunctionInitializer * @param constants constants array */ public StoredScript(final int compilationId, final String mainClassName, final Map classBytes, final Map initializers, final Object[] constants) { diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/ArrayData.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/ArrayData.java index f0a8c7a246b..ade9dce91b4 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/ArrayData.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/ArrayData.java @@ -275,7 +275,7 @@ public abstract class ArrayData { /** * Align an array size up to the nearest array chunk size * @param size size required - * @return size given, always >= size + * @return size given, always >= size */ protected final static int alignUp(final int size) { return size + CHUNK_SIZE - 1 & ~(CHUNK_SIZE - 1); diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/BoundCallableLinker.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/BoundCallableLinker.java index d52063bf3f5..b8710569e84 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/BoundCallableLinker.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/BoundCallableLinker.java @@ -99,7 +99,7 @@ final class BoundCallableLinker implements TypeBasedGuardingDynamicLinker { MethodType newMethodType = descriptor.getMethodType().changeParameterType(0, callable.getClass()); if (isCall) { // R(callable.class, T1, ...) => R(callable.class, boundThis.class, ...) - newMethodType = newMethodType.changeParameterType(1, boundThis.getClass()); + newMethodType = newMethodType.changeParameterType(1, boundThis == null? Object.class : boundThis.getClass()); } // R(callable.class[, boundThis.class], T2, ...) => R(callable.class[, boundThis.class], boundArg0.class, ..., boundArgn.class, T2, ...) for(int i = boundArgs.length; i-- > 0;) { diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/BrowserJSObjectLinker.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/BrowserJSObjectLinker.java index 0056477c325..f61802bd1c0 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/BrowserJSObjectLinker.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/BrowserJSObjectLinker.java @@ -40,6 +40,7 @@ import jdk.internal.dynalink.linker.TypeBasedGuardingDynamicLinker; import jdk.internal.dynalink.support.CallSiteDescriptorFactory; import jdk.nashorn.internal.lookup.MethodHandleFactory; import jdk.nashorn.internal.lookup.MethodHandleFunctionality; +import jdk.nashorn.internal.runtime.ConsString; import jdk.nashorn.internal.runtime.JSType; /** @@ -118,20 +119,21 @@ final class BrowserJSObjectLinker implements TypeBasedGuardingDynamicLinker { private GuardedInvocation lookup(final CallSiteDescriptor desc, final LinkRequest request, final LinkerServices linkerServices) throws Exception { final String operator = CallSiteDescriptorFactory.tokenizeOperators(desc).get(0); final int c = desc.getNameTokenCount(); + GuardedInvocation inv; + try { + inv = nashornBeansLinker.getGuardedInvocation(request, linkerServices); + } catch (Throwable th) { + inv = null; + } switch (operator) { case "getProp": case "getElem": case "getMethod": - if (c > 2) { - return findGetMethod(desc); - } - // For indexed get, we want GuardedInvocation from beans linker and pass it. - // BrowserJSObjectLinker.get uses this fallback getter for explicit signature method access. - return findGetIndexMethod(nashornBeansLinker.getGuardedInvocation(request, linkerServices)); + return c > 2? findGetMethod(desc, inv) : findGetIndexMethod(inv); case "setProp": case "setElem": - return c > 2 ? findSetMethod(desc) : findSetIndexMethod(); + return c > 2? findSetMethod(desc, inv) : findSetIndexMethod(); case "call": return findCallMethod(desc); default: @@ -139,7 +141,10 @@ final class BrowserJSObjectLinker implements TypeBasedGuardingDynamicLinker { } } - private static GuardedInvocation findGetMethod(final CallSiteDescriptor desc) { + private static GuardedInvocation findGetMethod(final CallSiteDescriptor desc, final GuardedInvocation inv) { + if (inv != null) { + return inv; + } final String name = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND); final MethodHandle getter = MH.insertArguments(JSOBJECT_GETMEMBER, 1, name); return new GuardedInvocation(getter, IS_JSOBJECT_GUARD); @@ -150,7 +155,10 @@ final class BrowserJSObjectLinker implements TypeBasedGuardingDynamicLinker { return inv.replaceMethods(getter, inv.getGuard()); } - private static GuardedInvocation findSetMethod(final CallSiteDescriptor desc) { + private static GuardedInvocation findSetMethod(final CallSiteDescriptor desc, final GuardedInvocation inv) { + if (inv != null) { + return inv; + } final MethodHandle getter = MH.insertArguments(JSOBJECT_SETMEMBER, 1, desc.getNameToken(2)); return new GuardedInvocation(getter, IS_JSOBJECT_GUARD); } @@ -178,12 +186,12 @@ final class BrowserJSObjectLinker implements TypeBasedGuardingDynamicLinker { if (index > -1) { return JSOBJECT_GETSLOT.invokeExact(jsobj, index); } - } else if (key instanceof String) { - final String name = (String)key; + } else if (key instanceof String || key instanceof ConsString) { + final String name = key.toString(); if (name.indexOf('(') != -1) { - return fallback.invokeExact(jsobj, key); + return fallback.invokeExact(jsobj, (Object) name); } - return JSOBJECT_GETMEMBER.invokeExact(jsobj, (String)key); + return JSOBJECT_GETMEMBER.invokeExact(jsobj, name); } return null; } @@ -194,8 +202,8 @@ final class BrowserJSObjectLinker implements TypeBasedGuardingDynamicLinker { JSOBJECT_SETSLOT.invokeExact(jsobj, (int)key, value); } else if (key instanceof Number) { JSOBJECT_SETSLOT.invokeExact(jsobj, getIndex((Number)key), value); - } else if (key instanceof String) { - JSOBJECT_SETMEMBER.invokeExact(jsobj, (String)key, value); + } else if (key instanceof String || key instanceof ConsString) { + JSOBJECT_SETMEMBER.invokeExact(jsobj, key.toString(), value); } } diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JSObjectLinker.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JSObjectLinker.java index aaf5a2c314b..48772ae6baa 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JSObjectLinker.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JSObjectLinker.java @@ -42,6 +42,7 @@ import jdk.internal.dynalink.support.CallSiteDescriptorFactory; import jdk.nashorn.api.scripting.JSObject; import jdk.nashorn.internal.lookup.MethodHandleFactory; import jdk.nashorn.internal.lookup.MethodHandleFunctionality; +import jdk.nashorn.internal.runtime.ConsString; import jdk.nashorn.internal.runtime.JSType; /** @@ -185,11 +186,11 @@ final class JSObjectLinker implements TypeBasedGuardingDynamicLinker, GuardingTy if (index > -1) { return ((JSObject)jsobj).getSlot(index); } - } else if (key instanceof String) { - final String name = (String)key; + } else if (key instanceof String || key instanceof ConsString) { + final String name = key.toString(); // get with method name and signature. delegate it to beans linker! if (name.indexOf('(') != -1) { - return fallback.invokeExact(jsobj, key); + return fallback.invokeExact(jsobj, (Object) name); } return ((JSObject)jsobj).getMember(name); } @@ -202,8 +203,8 @@ final class JSObjectLinker implements TypeBasedGuardingDynamicLinker, GuardingTy ((JSObject)jsobj).setSlot((Integer)key, value); } else if (key instanceof Number) { ((JSObject)jsobj).setSlot(getIndex((Number)key), value); - } else if (key instanceof String) { - ((JSObject)jsobj).setMember((String)key, value); + } else if (key instanceof String || key instanceof ConsString) { + ((JSObject)jsobj).setMember(key.toString(), value); } } diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/PrimitiveLookup.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/PrimitiveLookup.java index 2a536bbf0a3..6c2f8854608 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/PrimitiveLookup.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/PrimitiveLookup.java @@ -26,17 +26,23 @@ package jdk.nashorn.internal.runtime.linker; import static jdk.nashorn.internal.lookup.Lookup.MH; +import static jdk.nashorn.internal.runtime.ECMAErrors.typeError; + import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; import java.lang.invoke.SwitchPoint; import jdk.internal.dynalink.CallSiteDescriptor; import jdk.internal.dynalink.linker.GuardedInvocation; import jdk.internal.dynalink.linker.LinkRequest; +import jdk.internal.dynalink.support.CallSiteDescriptorFactory; import jdk.internal.dynalink.support.Guards; import jdk.nashorn.internal.runtime.Context; import jdk.nashorn.internal.runtime.FindProperty; import jdk.nashorn.internal.runtime.GlobalConstants; +import jdk.nashorn.internal.runtime.JSType; import jdk.nashorn.internal.runtime.ScriptObject; +import jdk.nashorn.internal.runtime.ScriptRuntime; import jdk.nashorn.internal.runtime.UserAccessorProperty; /** @@ -46,6 +52,11 @@ import jdk.nashorn.internal.runtime.UserAccessorProperty; */ public final class PrimitiveLookup { + /** Method handle to link setters on primitive base. See ES5 8.7.2. */ + private static final MethodHandle PRIMITIVE_SETTER = findOwnMH("primitiveSetter", + MH.type(void.class, ScriptObject.class, Object.class, Object.class, boolean.class, Object.class)); + + private PrimitiveLookup() { } @@ -87,40 +98,58 @@ public final class PrimitiveLookup { final ScriptObject wrappedReceiver, final MethodHandle wrapFilter, final MethodHandle protoFilter) { final CallSiteDescriptor desc = request.getCallSiteDescriptor(); + final String name; + final FindProperty find; - //checks whether the property name is hard-coded in the call-site (i.e. a getProp vs a getElem, or setProp vs setElem) - //if it is we can make assumptions on the property: that if it is not defined on primitive wrapper itself it never will be. - //so in that case we can skip creation of primitive wrapper and start our search with the prototype. if (desc.getNameTokenCount() > 2) { - final String name = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND); - final FindProperty find = wrappedReceiver.findProperty(name, true); + name = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND); + find = wrappedReceiver.findProperty(name, true); + } else { + name = null; + find = null; + } - if (find == null) { - // Give up early, give chance to BeanLinker and NashornBottomLinker to deal with it. - return null; - } + final String firstOp = CallSiteDescriptorFactory.tokenizeOperators(desc).get(0); - final SwitchPoint sp = find.getProperty().getBuiltinSwitchPoint(); //can use this instead of proto filter - if (sp instanceof Context.BuiltinSwitchPoint && !sp.hasBeenInvalidated()) { - return new GuardedInvocation(GlobalConstants.staticConstantGetter(find.getObjectValue()), guard, sp, null); - } + switch (firstOp) { + case "getProp": + case "getElem": + case "getMethod": + //checks whether the property name is hard-coded in the call-site (i.e. a getProp vs a getElem, or setProp vs setElem) + //if it is we can make assumptions on the property: that if it is not defined on primitive wrapper itself it never will be. + //so in that case we can skip creation of primitive wrapper and start our search with the prototype. + if (name != null) { + if (find == null) { + // Give up early, give chance to BeanLinker and NashornBottomLinker to deal with it. + return null; + } - if (find.isInherited() && !(find.getProperty() instanceof UserAccessorProperty)) { - // If property is found in the prototype object bind the method handle directly to - // the proto filter instead of going through wrapper instantiation below. - final ScriptObject proto = wrappedReceiver.getProto(); - final GuardedInvocation link = proto.lookup(desc, request); + final SwitchPoint sp = find.getProperty().getBuiltinSwitchPoint(); //can use this instead of proto filter + if (sp instanceof Context.BuiltinSwitchPoint && !sp.hasBeenInvalidated()) { + return new GuardedInvocation(GlobalConstants.staticConstantGetter(find.getObjectValue()), guard, sp, null); + } - if (link != null) { - final MethodHandle invocation = link.getInvocation(); //this contains the builtin switchpoint + if (find.isInherited() && !(find.getProperty() instanceof UserAccessorProperty)) { + // If property is found in the prototype object bind the method handle directly to + // the proto filter instead of going through wrapper instantiation below. + final ScriptObject proto = wrappedReceiver.getProto(); + final GuardedInvocation link = proto.lookup(desc, request); - final MethodHandle adaptedInvocation = MH.asType(invocation, invocation.type().changeParameterType(0, Object.class)); - final MethodHandle method = MH.filterArguments(adaptedInvocation, 0, protoFilter); - final MethodHandle protoGuard = MH.filterArguments(link.getGuard(), 0, protoFilter); - - return new GuardedInvocation(method, NashornGuards.combineGuards(guard, protoGuard)); + if (link != null) { + final MethodHandle invocation = link.getInvocation(); //this contains the builtin switchpoint + final MethodHandle adaptedInvocation = MH.asType(invocation, invocation.type().changeParameterType(0, Object.class)); + final MethodHandle method = MH.filterArguments(adaptedInvocation, 0, protoFilter); + final MethodHandle protoGuard = MH.filterArguments(link.getGuard(), 0, protoFilter); + return new GuardedInvocation(method, NashornGuards.combineGuards(guard, protoGuard)); + } } } + break; + case "setProp": + case "setElem": + return getPrimitiveSetter(name, guard, wrapFilter, NashornCallSiteDescriptor.isStrict(desc)); + default: + break; } final GuardedInvocation link = wrappedReceiver.lookup(desc, request); @@ -138,4 +167,41 @@ public final class PrimitiveLookup { return null; } + + private static GuardedInvocation getPrimitiveSetter(final String name, final MethodHandle guard, + final MethodHandle wrapFilter, final boolean isStrict) { + MethodHandle filter = MH.asType(wrapFilter, wrapFilter.type().changeReturnType(ScriptObject.class)); + final MethodHandle target; + + if (name == null) { + filter = MH.dropArguments(filter, 1, Object.class, Object.class); + target = MH.insertArguments(PRIMITIVE_SETTER, 3, isStrict); + } else { + filter = MH.dropArguments(filter, 1, Object.class); + target = MH.insertArguments(PRIMITIVE_SETTER, 2, name, isStrict); + } + + return new GuardedInvocation(MH.foldArguments(target, filter), guard); + } + + + @SuppressWarnings("unused") + private static void primitiveSetter(final ScriptObject wrappedSelf, final Object self, final Object key, + final boolean strict, final Object value) { + // See ES5.1 8.7.2 PutValue (V, W) + final String name = JSType.toString(key); + final FindProperty find = wrappedSelf.findProperty(name, true); + if (find == null || !(find.getProperty() instanceof UserAccessorProperty) || !find.getProperty().isWritable()) { + if (strict) { + throw typeError("property.not.writable", name, ScriptRuntime.safeToString(self)); + } + return; + } + // property found and is a UserAccessorProperty + find.setValue(value, strict); + } + + private static MethodHandle findOwnMH(final String name, final MethodType type) { + return MH.findStatic(MethodHandles.lookup(), PrimitiveLookup.class, name, type); + } } diff --git a/nashorn/test/script/basic/JDK-8055762.js b/nashorn/test/script/basic/JDK-8055762.js index e772a579f4e..a0aac526937 100644 --- a/nashorn/test/script/basic/JDK-8055762.js +++ b/nashorn/test/script/basic/JDK-8055762.js @@ -74,9 +74,12 @@ function test(JSObject) { } }; + var a = "a"; print(obj["foo"]); + print(obj[a + "bc"]); print(obj[2]); obj.bar = 23; + obj[a + "bc"] = 23; obj[3] = 23; obj.func("hello"); } diff --git a/nashorn/test/script/basic/JDK-8055762.js.EXPECTED b/nashorn/test/script/basic/JDK-8055762.js.EXPECTED index 51a02015dd4..1cba6465a93 100644 --- a/nashorn/test/script/basic/JDK-8055762.js.EXPECTED +++ b/nashorn/test/script/basic/JDK-8055762.js.EXPECTED @@ -1,5 +1,7 @@ FOO +ABC 0 bar set to 23 +abc set to 23 [3] set to 23 func called with hello diff --git a/nashorn/test/script/basic/JDK-8066215.js b/nashorn/test/script/basic/JDK-8066215.js new file mode 100644 index 00000000000..3987fd89ae8 --- /dev/null +++ b/nashorn/test/script/basic/JDK-8066215.js @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2010, 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. + */ + +/** + * JDK-8066215: Fuzzing bug: length valueOf bug + * + * @test + * @run + */ + +function defineLength(arr, length) { + Object.defineProperty(arr, "length", { + value: { + valueOf: function() { + print("value retrieved: " + length); + return length; + } + } + }); + print("done: " + arr.length + ", " + typeof arr.length); +} + +var a = []; +defineLength(a, 3); +defineLength(a, 6); +defineLength(a, 3); diff --git a/nashorn/test/script/basic/JDK-8066215.js.EXPECTED b/nashorn/test/script/basic/JDK-8066215.js.EXPECTED new file mode 100644 index 00000000000..f10edda4287 --- /dev/null +++ b/nashorn/test/script/basic/JDK-8066215.js.EXPECTED @@ -0,0 +1,9 @@ +value retrieved: 3 +value retrieved: 3 +done: 3, number +value retrieved: 6 +value retrieved: 6 +done: 6, number +value retrieved: 3 +value retrieved: 3 +done: 3, number diff --git a/nashorn/test/script/basic/JDK-8066226.js b/nashorn/test/script/basic/JDK-8066226.js new file mode 100644 index 00000000000..7c43da9c351 --- /dev/null +++ b/nashorn/test/script/basic/JDK-8066226.js @@ -0,0 +1,132 @@ +/* + * 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. + */ + +/** + * + JDK-8066226: Fuzzing bug: parameter counts differ in TypeConverterFactory + * + * @test + * @run + */ + +Object.defineProperty(Object.prototype, "accessor", { + set: function(value) { + print("Setting accessor on " + this + " to " + value); + } +}); + +Object.defineProperty(Object.prototype, "getterOnly", { + get: function() { + return 1; + } +}); + +function set(o) { + print("set(" + o + ")"); + o.foo = 1; + o.constructor = 1; + o.accessor = 1; + o.getterOnly = 1; + print(); +} + +function setStrict(o) { + "use strict"; + print("setStrict(" + o + ")") + try { + o.foo = 1; + } catch (e) { + print(e); + } + try { + o.constructor = 1; + } catch (e) { + print(e); + } + try { + o.accessor = 1; + } catch (e) { + print(e); + } + try { + o.getterOnly = 1; + } catch (e) { + print(e); + } + print(); +} + +function setAttr(o, id) { + print("setAttr(" + o + ", " + id + ")") + o[id] = 1; + print(); +} + +function setAttrStrict(o, id) { + "use strict"; + print("setAttrStrict(" + o + ", " + id + ")") + try { + o[id] = 1; + } catch (e) { + print(e); + } + print(); +} + +set(1); +set("str"); +set(true); +set({}); +set([]); + +setStrict(1); +setStrict("str"); +setStrict(true); +setStrict({}); +setStrict([]); + +setAttr(1, "foo"); +setAttr(1, "constructor"); +setAttr(1, "accessor"); +setAttr(1, "getterOnly"); +setAttr("str", "foo"); +setAttr("str", "constructor"); +setAttr("str", "accessor"); +setAttr("str", "getterOnly"); +setAttr(true, "foo"); +setAttr(true, "constructor"); +setAttr(true, "accessor"); +setAttr(true, "getterOnly"); + +setAttrStrict(1, "foo"); +setAttrStrict(1, "constructor"); +setAttrStrict(1, "accessor"); +setAttrStrict(1, "getterOnly"); +setAttrStrict("str", "foo"); +setAttrStrict("str", "constructor"); +setAttrStrict("str", "accessor"); +setAttrStrict("str", "getterOnly"); +setAttrStrict(true, "foo"); +setAttrStrict(true, "constructor"); +setAttrStrict(true, "accessor"); +setAttrStrict(true, "getterOnly"); diff --git a/nashorn/test/script/basic/JDK-8066226.js.EXPECTED b/nashorn/test/script/basic/JDK-8066226.js.EXPECTED new file mode 100644 index 00000000000..7c6c3e1d62e --- /dev/null +++ b/nashorn/test/script/basic/JDK-8066226.js.EXPECTED @@ -0,0 +1,104 @@ +set(1) +Setting accessor on 1 to 1 + +set(str) +Setting accessor on str to 1 + +set(true) +Setting accessor on true to 1 + +set([object Object]) +Setting accessor on [object Object] to 1 + +set() +Setting accessor on to 1 + +setStrict(1) +TypeError: "foo" is not a writable property of 1 +TypeError: "constructor" is not a writable property of 1 +Setting accessor on 1 to 1 +TypeError: Cannot set property "getterOnly" of [object Object] that has only a getter + +setStrict(str) +TypeError: "foo" is not a writable property of str +TypeError: "constructor" is not a writable property of str +Setting accessor on str to 1 +TypeError: Cannot set property "getterOnly" of [object Object] that has only a getter + +setStrict(true) +TypeError: "foo" is not a writable property of true +TypeError: "constructor" is not a writable property of true +Setting accessor on true to 1 +TypeError: Cannot set property "getterOnly" of [object Object] that has only a getter + +setStrict([object Object]) +Setting accessor on [object Object] to 1 +TypeError: Cannot set property "getterOnly" of [object Object] that has only a getter + +setStrict() +Setting accessor on to 1 +TypeError: Cannot set property "getterOnly" of [object Array] that has only a getter + +setAttr(1, foo) + +setAttr(1, constructor) + +setAttr(1, accessor) +Setting accessor on 1 to 1 + +setAttr(1, getterOnly) + +setAttr(str, foo) + +setAttr(str, constructor) + +setAttr(str, accessor) +Setting accessor on str to 1 + +setAttr(str, getterOnly) + +setAttr(true, foo) + +setAttr(true, constructor) + +setAttr(true, accessor) +Setting accessor on true to 1 + +setAttr(true, getterOnly) + +setAttrStrict(1, foo) +TypeError: "foo" is not a writable property of 1 + +setAttrStrict(1, constructor) +TypeError: "constructor" is not a writable property of 1 + +setAttrStrict(1, accessor) +Setting accessor on 1 to 1 + +setAttrStrict(1, getterOnly) +TypeError: Cannot set property "getterOnly" of [object Object] that has only a getter + +setAttrStrict(str, foo) +TypeError: "foo" is not a writable property of str + +setAttrStrict(str, constructor) +TypeError: "constructor" is not a writable property of str + +setAttrStrict(str, accessor) +Setting accessor on str to 1 + +setAttrStrict(str, getterOnly) +TypeError: Cannot set property "getterOnly" of [object Object] that has only a getter + +setAttrStrict(true, foo) +TypeError: "foo" is not a writable property of true + +setAttrStrict(true, constructor) +TypeError: "constructor" is not a writable property of true + +setAttrStrict(true, accessor) +Setting accessor on true to 1 + +setAttrStrict(true, getterOnly) +TypeError: Cannot set property "getterOnly" of [object Object] that has only a getter + diff --git a/nashorn/test/script/basic/JDK-8067774.js b/nashorn/test/script/basic/JDK-8067774.js new file mode 100644 index 00000000000..4eeeb8d829d --- /dev/null +++ b/nashorn/test/script/basic/JDK-8067774.js @@ -0,0 +1,37 @@ +/* + * 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. + */ + +/** + * JDK-8067774: Use a stack of types when calculating local variable types + * + * @test + * @run + */ + +print((function (p) { + var a, b; + + a = p ? ((b = 1), b) : 0; + + return a; +})(true)); diff --git a/nashorn/test/script/basic/JDK-8067774.js.EXPECTED b/nashorn/test/script/basic/JDK-8067774.js.EXPECTED new file mode 100644 index 00000000000..d00491fd7e5 --- /dev/null +++ b/nashorn/test/script/basic/JDK-8067774.js.EXPECTED @@ -0,0 +1 @@ +1 diff --git a/nashorn/test/script/trusted/JDK-8067854.js b/nashorn/test/script/trusted/JDK-8067854.js new file mode 100644 index 00000000000..487bd77bbfc --- /dev/null +++ b/nashorn/test/script/trusted/JDK-8067854.js @@ -0,0 +1,39 @@ +/* + * 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. + */ + +/** + * JDK-8067854: bound java static method throws NPE when 'null' is used for this argument + * + * @test + * @run + */ + +getProp = java.lang.System.getProperty; + +// bind this and an argument. "null" for this as getProperty is a +// static method of java.lang.System +getHome = Function.prototype.bind.call(getProp, null, "java.home"); + +if (getHome() != getProp("java.home")) { + fail("getHome() failed to get java.home"); +} diff --git a/nashorn/test/src/jdk/nashorn/api/scripting/PluggableJSObjectTest.java b/nashorn/test/src/jdk/nashorn/api/scripting/PluggableJSObjectTest.java index b277bdefddc..d6b9dcde1e5 100644 --- a/nashorn/test/src/jdk/nashorn/api/scripting/PluggableJSObjectTest.java +++ b/nashorn/test/src/jdk/nashorn/api/scripting/PluggableJSObjectTest.java @@ -109,6 +109,35 @@ public class PluggableJSObjectTest { } } + // @bug 8062030: Nashorn bug retrieving array property after key string concatenation + @Test + // ConsString attribute access on a JSObject + public void consStringTest() { + final ScriptEngineManager m = new ScriptEngineManager(); + final ScriptEngine e = m.getEngineByName("nashorn"); + try { + final MapWrapperObject obj = new MapWrapperObject(); + e.put("obj", obj); + e.put("f", "f"); + e.eval("obj[f + 'oo'] = 'bar';"); + + assertEquals(obj.getMap().get("foo"), "bar"); + assertEquals(e.eval("obj[f + 'oo']"), "bar"); + assertEquals(e.eval("obj['foo']"), "bar"); + assertEquals(e.eval("f + 'oo' in obj"), Boolean.TRUE); + assertEquals(e.eval("'foo' in obj"), Boolean.TRUE); + e.eval("delete obj[f + 'oo']"); + assertFalse(obj.getMap().containsKey("foo")); + assertEquals(e.eval("obj[f + 'oo']"), null); + assertEquals(e.eval("obj['foo']"), null); + assertEquals(e.eval("f + 'oo' in obj"), Boolean.FALSE); + assertEquals(e.eval("'foo' in obj"), Boolean.FALSE); + } catch (final Exception exp) { + exp.printStackTrace(); + fail(exp.getMessage()); + } + } + public static class BufferObject extends AbstractJSObject { private final IntBuffer buf; diff --git a/test/Makefile b/test/Makefile index 89141cce04b..64d93fc929a 100644 --- a/test/Makefile +++ b/test/Makefile @@ -33,6 +33,7 @@ TOPDIR=.. # This makefile depends on the availability of sibling directories. LANGTOOLS_DIR=$(TOPDIR)/langtools JDK_DIR=$(TOPDIR)/jdk +JAXP_DIR=$(TOPDIR)/jaxp HOTSPOT_DIR=$(TOPDIR)/hotspot # Macro to run a test target in a subdir @@ -51,10 +52,10 @@ fi endef # Default test target (core) -default: jdk_core langtools_jtreg +default: jdk_core langtools_jtreg jaxp_all # All testing -all: jdk_all langtools_all +all: jdk_all langtools_all jaxp_all # Test targets langtools_% : @@ -63,6 +64,9 @@ langtools_% : jdk_% core_%s svc_%: @$(NO_STOPPING)$(call SUBDIR_TEST, $(JDK_DIR), TEST="$@" $@) +jaxp_%: + @$(NO_STOPPING)$(call SUBDIR_TEST, $(JAXP_DIR), TEST="$@" $@) + hotspot_%: @$(NO_STOPPING)$(call SUBDIR_TEST, $(HOTSPOT_DIR), TEST="$@" $@) diff --git a/hotspot/test/testlibrary/whitebox/Makefile b/test/lib/Makefile similarity index 89% rename from hotspot/test/testlibrary/whitebox/Makefile rename to test/lib/Makefile index 8a84a0a4492..37e5071abaf 100644 --- a/hotspot/test/testlibrary/whitebox/Makefile +++ b/test/lib/Makefile @@ -1,5 +1,5 @@ # -# Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. +# 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 @@ -20,7 +20,9 @@ # or visit www.oracle.com if you need additional information or have any # questions. # -# + +# Utility Makefile that creates wb.jar, which is used to simplify using +# the Whitebox API outside the jtreg-testbase. ifneq "x$(ALT_BOOTDIR)" "x" BOOTDIR := $(ALT_BOOTDIR) diff --git a/hotspot/test/testlibrary/whitebox/sun/hotspot/WhiteBox.java b/test/lib/sun/hotspot/WhiteBox.java similarity index 94% rename from hotspot/test/testlibrary/whitebox/sun/hotspot/WhiteBox.java rename to test/lib/sun/hotspot/WhiteBox.java index 35f5a9c1109..4da988a8fd5 100644 --- a/hotspot/test/testlibrary/whitebox/sun/hotspot/WhiteBox.java +++ b/test/lib/sun/hotspot/WhiteBox.java @@ -109,6 +109,7 @@ public class WhiteBox { public native int NMTGetHashSize(); // Compiler + public native int deoptimizeFrames(boolean makeNotEntrant); public native void deoptimizeAll(); public boolean isMethodCompiled(Executable method) { return isMethodCompiled(method, false /*not osr*/); @@ -153,6 +154,14 @@ public class WhiteBox { public native int getMethodEntryBci(Executable method); public native Object[] getNMethod(Executable method, boolean isOsr); public native long allocateCodeBlob(int size, int type); + public long allocateCodeBlob(long size, int type) { + int intSize = (int) size; + if ((long) intSize != size || size < 0) { + throw new IllegalArgumentException( + "size argument has illegal value " + size); + } + return allocateCodeBlob( intSize, type); + } public native void freeCodeBlob(long addr); public void forceNMethodSweep() { try { @@ -240,4 +249,6 @@ public class WhiteBox { return offset; } + // Safepoint Checking + public native void assertMatchingSafepointCalls(boolean mutexSafepointValue, boolean attemptedNoSafepointValue); } diff --git a/hotspot/test/testlibrary/whitebox/sun/hotspot/code/BlobType.java b/test/lib/sun/hotspot/code/BlobType.java similarity index 100% rename from hotspot/test/testlibrary/whitebox/sun/hotspot/code/BlobType.java rename to test/lib/sun/hotspot/code/BlobType.java diff --git a/hotspot/test/testlibrary/whitebox/sun/hotspot/code/CodeBlob.java b/test/lib/sun/hotspot/code/CodeBlob.java similarity index 100% rename from hotspot/test/testlibrary/whitebox/sun/hotspot/code/CodeBlob.java rename to test/lib/sun/hotspot/code/CodeBlob.java diff --git a/hotspot/test/testlibrary/whitebox/sun/hotspot/code/NMethod.java b/test/lib/sun/hotspot/code/NMethod.java similarity index 100% rename from hotspot/test/testlibrary/whitebox/sun/hotspot/code/NMethod.java rename to test/lib/sun/hotspot/code/NMethod.java diff --git a/hotspot/test/testlibrary/whitebox/sun/hotspot/cpuinfo/CPUInfo.java b/test/lib/sun/hotspot/cpuinfo/CPUInfo.java similarity index 99% rename from hotspot/test/testlibrary/whitebox/sun/hotspot/cpuinfo/CPUInfo.java rename to test/lib/sun/hotspot/cpuinfo/CPUInfo.java index 8532573a94c..51c78c1acef 100644 --- a/hotspot/test/testlibrary/whitebox/sun/hotspot/cpuinfo/CPUInfo.java +++ b/test/lib/sun/hotspot/cpuinfo/CPUInfo.java @@ -25,7 +25,6 @@ package sun.hotspot.cpuinfo; import java.util.List; -import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.regex.Pattern; diff --git a/hotspot/test/testlibrary/whitebox/sun/hotspot/parser/DiagnosticCommand.java b/test/lib/sun/hotspot/parser/DiagnosticCommand.java similarity index 97% rename from hotspot/test/testlibrary/whitebox/sun/hotspot/parser/DiagnosticCommand.java rename to test/lib/sun/hotspot/parser/DiagnosticCommand.java index 11a0c2b4e1b..1ad6217ad59 100644 --- a/hotspot/test/testlibrary/whitebox/sun/hotspot/parser/DiagnosticCommand.java +++ b/test/lib/sun/hotspot/parser/DiagnosticCommand.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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