# HG changeset patch # User Thomas Wuerthinger # Date 1362523494 -3600 # Node ID 5fc51c1ecdeb6d9b4b85be9710576f9ff023d71b # Parent a413bcd552a4293f469cefc03280c3111d5f777c# Parent 4a198b201f3ce84433fa94a3ca65d061473e7c4c Merge. diff -r a413bcd552a4 -r 5fc51c1ecdeb .hgtags --- a/.hgtags Tue Mar 05 21:58:51 2013 +0100 +++ b/.hgtags Tue Mar 05 23:44:54 2013 +0100 @@ -311,3 +311,12 @@ 70c89bd6b895a10d25ca70e08093c09ff2005fda hs25-b16 1a3e54283c54aaa8b3437813e8507fbdc966e5b6 jdk8-b74 b4391649e91ea8d37f66317a03d6d2573a93d10d hs25-b17 +6778d0b1659323a506ca47600ca29a9d9f8b383d jdk8-b75 +20b605466ccb1b3725eb25314d9e8782199630c5 jdk8-b76 +412d722168bc23f8e6d98995202728678561417f hs25-b18 +cdb46031e7184d37301288f5719121a63c7054b5 jdk8-b77 +9f19f4a7d48a4ebe7f616b6068971ea5f8b075fa hs25-b19 +d5e12e7d2f719144d84903d9151455661c47b476 jdk8-b78 +555ec35a250783110aa070dbc8a8603f6cabe41f hs25-b20 +6691814929b606fe0e7954fd6e485dd876505c83 jdk8-b79 +df5396524152118535c36da5801d828b560d19a2 hs25-b21 diff -r a413bcd552a4 -r 5fc51c1ecdeb agent/make/Makefile --- a/agent/make/Makefile Tue Mar 05 21:58:51 2013 +0100 +++ b/agent/make/Makefile Tue Mar 05 23:44:54 2013 +0100 @@ -19,7 +19,7 @@ # 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. -# +# # # This guards against adding broken .java files to the directory @@ -42,8 +42,6 @@ sun.jvm.hotspot \ sun.jvm.hotspot.asm \ sun.jvm.hotspot.asm.sparc \ -sun.jvm.hotspot.bugspot \ -sun.jvm.hotspot.bugspot.tree \ sun.jvm.hotspot.c1 \ sun.jvm.hotspot.ci \ sun.jvm.hotspot.code \ @@ -84,7 +82,6 @@ sun.jvm.hotspot.gc_interface \ sun.jvm.hotspot.interpreter \ sun.jvm.hotspot.jdi \ -sun.jvm.hotspot.livejvm \ sun.jvm.hotspot.memory \ sun.jvm.hotspot.opto \ sun.jvm.hotspot.oops \ @@ -130,8 +127,6 @@ sun/jvm/hotspot/*.java \ sun/jvm/hotspot/asm/*.java \ sun/jvm/hotspot/asm/sparc/*.java \ -sun/jvm/hotspot/bugspot/*.java \ -sun/jvm/hotspot/bugspot/tree/*.java \ sun/jvm/hotspot/c1/*.java \ sun/jvm/hotspot/ci/*.java \ sun/jvm/hotspot/code/*.java \ @@ -168,7 +163,6 @@ sun/jvm/hotspot/gc_implementation/shared/*.java \ sun/jvm/hotspot/interpreter/*.java \ sun/jvm/hotspot/jdi/*.java \ -sun/jvm/hotspot/livejvm/*.java \ sun/jvm/hotspot/memory/*.java \ sun/jvm/hotspot/oops/*.java \ sun/jvm/hotspot/opto/*.java \ @@ -205,7 +199,7 @@ sun/jvm/hotspot/utilities/memo/*.java \ sun/jvm/hotspot/utilities/soql/*.java \ com/sun/java/swing/action/*.java \ -com/sun/java/swing/ui/*.java +com/sun/java/swing/ui/*.java #END FILELIST ifneq "x$(ALT_BOOTDIR)" "x" @@ -231,7 +225,7 @@ OUTPUT_DIR = $(BUILD_DIR)/classes DOC_DIR = $(BUILD_DIR)/doc -# gnumake 3.78.1 does not accept the *s, +# gnumake 3.78.1 does not accept the *s, # so use the shell to expand them ALLFILES := $(patsubst %,$(SRC_DIR)/%,$(FILELIST)) ALLFILES := $(shell /bin/ls $(ALLFILES)) @@ -303,7 +297,7 @@ cscope: $(ALLFILES) rm -f java.files echo $(ALLFILES) > java.files - cscope -b -i java.files -f java.out + cscope -b -i java.files -f java.out rm -f java.files .PHONY: sa.jar diff -r a413bcd552a4 -r 5fc51c1ecdeb agent/make/bugspot.bat --- a/agent/make/bugspot.bat Tue Mar 05 21:58:51 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,25 +0,0 @@ -REM -REM Copyright (c) 2002, 2008, Oracle and/or its affiliates. All rights reserved. -REM DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -REM -REM This code is free software; you can redistribute it and/or modify it -REM under the terms of the GNU General Public License version 2 only, as -REM published by the Free Software Foundation. -REM -REM This code is distributed in the hope that it will be useful, but WITHOUT -REM ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -REM FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -REM version 2 for more details (a copy is included in the LICENSE file that -REM accompanied this code). -REM -REM You should have received a copy of the GNU General Public License version -REM 2 along with this work; if not, write to the Free Software Foundation, -REM Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -REM -REM Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -REM or visit www.oracle.com if you need additional information or have any -REM questions. -REM -REM - -java -showversion -cp ..\build\classes;..\src\share\lib\js.jar;.\sa.jar;lib\js.jar sun.jvm.hotspot.bugspot.Main diff -r a413bcd552a4 -r 5fc51c1ecdeb agent/make/marks_notes.html --- a/agent/make/marks_notes.html Tue Mar 05 21:58:51 2013 +0100 +++ b/agent/make/marks_notes.html Tue Mar 05 23:44:54 2013 +0100 @@ -26,14 +26,12 @@

Feedback

Refactoring of package hierarchy. All user interface components should be in - the ui package. Perhaps: sun.jvm.hotspot.ui.hsdb.Main for the HSDB and - sun.jvm.hotspot.ui.bugspot.Main for BugSpot. + the ui package. Perhaps: sun.jvm.hotspot.ui.hsdb.Main for the HSDB.

The src\share\vm\agent area seems like a workspace so it should be organized like one. In particular, I'd like to suggest the following directory layout:
@@ -47,7 +45,7 @@

- Seems like there is a lot of redundant functionality. Between the HSDB and BugSpot. Perhaps + Seems like there is a lot of redundant functionality. Perhaps this can be consolidated with a javax.swing.Actions architecture.

Tasklist

@@ -55,11 +53,7 @@

Stack memory pane: It's one of the more useful JVM debugging tools in the SA. However, it - doesn't support any interaction with the text; the Memory Panel in BugSpot - was written afterward (with help from Shannon) and implements proper - selection, scrolling, and drag-and-drop, but no annotations. I'm not sure how - to integrate the annotations with the JTable that's being used for the memory - view; if you have suggestions here please let me know. + doesn't support any interaction with the text.

Integrations with the NetBeans architecture (plug in). See the Netbeans Open APIs homepage diff -r a413bcd552a4 -r 5fc51c1ecdeb agent/src/os/bsd/MacosxDebuggerLocal.m --- a/agent/src/os/bsd/MacosxDebuggerLocal.m Tue Mar 05 21:58:51 2013 +0100 +++ b/agent/src/os/bsd/MacosxDebuggerLocal.m Tue Mar 05 23:44:54 2013 +0100 @@ -38,6 +38,8 @@ #import #import #import +#import +#import jboolean debug = JNI_FALSE; @@ -97,7 +99,8 @@ * Method: init0 * Signature: ()V */ -JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_init0(JNIEnv *env, jclass cls) { +JNIEXPORT void JNICALL +Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_init0(JNIEnv *env, jclass cls) { symbolicatorID = (*env)->GetFieldID(env, cls, "symbolicator", "J"); taskID = (*env)->GetFieldID(env, cls, "task", "J"); CHECK_EXCEPTION; @@ -108,7 +111,11 @@ * Method: lookupByName0 * Signature: (Ljava/lang/String;Ljava/lang/String;)J */ -JNIEXPORT jlong JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_lookupByName0(JNIEnv *env, jobject this_obj, jstring objectName, jstring symbolName) { +JNIEXPORT jlong JNICALL +Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_lookupByName0( + JNIEnv *env, jobject this_obj, + jstring objectName, jstring symbolName) +{ jlong address = 0; JNF_COCOA_ENTER(env); @@ -137,7 +144,11 @@ * Method: readBytesFromProcess0 * Signature: (JJ)Lsun/jvm/hotspot/debugger/ReadResult; */ -JNIEXPORT jbyteArray JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_readBytesFromProcess0(JNIEnv *env, jobject this_obj, jlong addr, jlong numBytes) { +JNIEXPORT jbyteArray JNICALL +Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_readBytesFromProcess0( + JNIEnv *env, jobject this_obj, + jlong addr, jlong numBytes) +{ if (debug) printf("readBytesFromProcess called. addr = %llx numBytes = %lld\n", addr, numBytes); // must allocate storage instead of using former parameter buf @@ -209,12 +220,74 @@ return array; } + /* - * Class: sun_jvm_hotspot_debugger_macosx_MacOSXDebuggerLocal + * Lookup the thread_t that corresponds to the given thread_id. + * The thread_id should be the result from calling thread_info() with THREAD_IDENTIFIER_INFO + * and reading the m_ident_info.thread_id returned. + * The returned thread_t is the mach send right to the kernel port for the corresponding thread. + * + * We cannot simply use the OSThread._thread_id field in the JVM. This is set to ::mach_thread_self() + * in the VM, but that thread port is not valid for a remote debugger to access the thread. + */ +thread_t +lookupThreadFromThreadId(task_t task, jlong thread_id) { + if (debug) { + printf("lookupThreadFromThreadId thread_id=0x%llx\n", thread_id); + } + + thread_array_t thread_list = NULL; + mach_msg_type_number_t thread_list_count = 0; + thread_t result_thread = 0; + int i; + + // get the list of all the send rights + kern_return_t result = task_threads(task, &thread_list, &thread_list_count); + if (result != KERN_SUCCESS) { + if (debug) { + printf("task_threads returned 0x%x\n", result); + } + return 0; + } + + for(i = 0 ; i < thread_list_count; i++) { + thread_identifier_info_data_t m_ident_info; + mach_msg_type_number_t count = THREAD_IDENTIFIER_INFO_COUNT; + + // get the THREAD_IDENTIFIER_INFO for the send right + result = thread_info(thread_list[i], THREAD_IDENTIFIER_INFO, (thread_info_t) &m_ident_info, &count); + if (result != KERN_SUCCESS) { + if (debug) { + printf("thread_info returned 0x%x\n", result); + } + break; + } + + // if this is the one we're looking for, return the send right + if (thread_id == m_ident_info.thread_id) + { + result_thread = thread_list[i]; + break; + } + } + + vm_size_t thread_list_size = (vm_size_t) (thread_list_count * sizeof (thread_t)); + vm_deallocate(mach_task_self(), (vm_address_t) thread_list, thread_list_count); + + return result_thread; +} + + +/* + * Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal * Method: getThreadIntegerRegisterSet0 - * Signature: (I)[J + * Signature: (J)[J */ -JNIEXPORT jlongArray JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_getThreadIntegerRegisterSet0(JNIEnv *env, jobject this_obj, jint lwp_id) { +JNIEXPORT jlongArray JNICALL +Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_getThreadIntegerRegisterSet0( + JNIEnv *env, jobject this_obj, + jlong thread_id) +{ if (debug) printf("getThreadRegisterSet0 called\n"); @@ -226,8 +299,9 @@ int i; jlongArray registerArray; jlong *primitiveArray; + task_t gTask = getTask(env, this_obj); - tid = lwp_id; + tid = lookupThreadFromThreadId(gTask, thread_id); result = thread_get_state(tid, HSDB_THREAD_STATE, (thread_state_t)&state, &count); @@ -328,19 +402,21 @@ } /* - * Class: sun_jvm_hotspot_debugger_macosx_MacOSXDebuggerLocal + * Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal * Method: translateTID0 * Signature: (I)I */ JNIEXPORT jint JNICALL -Java_sun_jvm_hotspot_debugger_macosx_MacOSXDebuggerLocal_translateTID0(JNIEnv *env, jobject this_obj, jint tid) { +Java_sun_jvm_hotspot_debugger_macosx_MacOSXDebuggerLocal_translateTID0( + JNIEnv *env, jobject this_obj, jint tid) +{ if (debug) printf("translateTID0 called on tid = 0x%x\n", (int)tid); kern_return_t result; thread_t foreign_tid, usable_tid; mach_msg_type_name_t type; - + foreign_tid = tid; task_t gTask = getTask(env, this_obj); @@ -356,19 +432,90 @@ return (jint) usable_tid; } + +static bool ptrace_continue(pid_t pid, int signal) { + // pass the signal to the process so we don't swallow it + int res; + if ((res = ptrace(PT_CONTINUE, pid, (caddr_t)1, signal)) < 0) { + fprintf(stderr, "attach: ptrace(PT_CONTINUE, %d) failed with %d\n", pid, res); + return false; + } + return true; +} + +// waits until the ATTACH has stopped the process +// by signal SIGSTOP +static bool ptrace_waitpid(pid_t pid) { + int ret; + int status; + while (true) { + // Wait for debuggee to stop. + ret = waitpid(pid, &status, 0); + if (ret >= 0) { + if (WIFSTOPPED(status)) { + // Any signal will stop the thread, make sure it is SIGSTOP. Otherwise SIGSTOP + // will still be pending and delivered when the process is DETACHED and the process + // will go to sleep. + if (WSTOPSIG(status) == SIGSTOP) { + // Debuggee stopped by SIGSTOP. + return true; + } + if (!ptrace_continue(pid, WSTOPSIG(status))) { + fprintf(stderr, "attach: Failed to correctly attach to VM. VM might HANG! [PTRACE_CONT failed, stopped by %d]\n", WSTOPSIG(status)); + return false; + } + } else { + fprintf(stderr, "attach: waitpid(): Child process exited/terminated (status = 0x%x)\n", status); + return false; + } + } else { + switch (errno) { + case EINTR: + continue; + break; + case ECHILD: + fprintf(stderr, "attach: waitpid() failed. Child process pid (%d) does not exist \n", pid); + break; + case EINVAL: + fprintf(stderr, "attach: waitpid() failed. Invalid options argument.\n"); + break; + default: + fprintf(stderr, "attach: waitpid() failed. Unexpected error %d\n",errno); + break; + } + return false; + } + } +} + +// attach to a process/thread specified by "pid" +static bool ptrace_attach(pid_t pid) { + int res; + if ((res = ptrace(PT_ATTACH, pid, 0, 0)) < 0) { + fprintf(stderr, "ptrace(PT_ATTACH, %d) failed with %d\n", pid, res); + return false; + } else { + return ptrace_waitpid(pid); + } +} + /* * Class: sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal * Method: attach0 * Signature: (I)V */ -JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_attach0__I(JNIEnv *env, jobject this_obj, jint jpid) { +JNIEXPORT void JNICALL +Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_attach0__I( + JNIEnv *env, jobject this_obj, jint jpid) +{ JNF_COCOA_ENTER(env); if (getenv("JAVA_SAPROC_DEBUG") != NULL) debug = JNI_TRUE; else debug = JNI_FALSE; if (debug) printf("attach0 called for jpid=%d\n", (int)jpid); - + + // get the task from the pid kern_return_t result; task_t gTask = 0; result = task_for_pid(mach_task_self(), jpid, &gTask); @@ -378,6 +525,13 @@ } putTask(env, this_obj, gTask); + // use ptrace to stop the process + // on os x, ptrace only needs to be called on the process, not the individual threads + if (ptrace_attach(jpid) != true) { + mach_port_deallocate(mach_task_self(), gTask); + THROW_NEW_DEBUGGER_EXCEPTION("Can't attach to the process"); + } + id symbolicator = nil; id jrsSymbolicator = objc_lookUpClass("JRSSymbolicator"); if (jrsSymbolicator != nil) { @@ -401,11 +555,29 @@ * Method: detach0 * Signature: ()V */ -JNIEXPORT void JNICALL Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_detach0(JNIEnv *env, jobject this_obj) { +JNIEXPORT void JNICALL +Java_sun_jvm_hotspot_debugger_bsd_BsdDebuggerLocal_detach0( + JNIEnv *env, jobject this_obj) +{ JNF_COCOA_ENTER(env); if (debug) printf("detach0 called\n"); task_t gTask = getTask(env, this_obj); + + // detach from the ptraced process causing it to resume execution + int pid; + kern_return_t k_res; + k_res = pid_for_task(gTask, &pid); + if (k_res != KERN_SUCCESS) { + fprintf(stderr, "detach: pid_for_task(%d) failed (%d)\n", pid, k_res); + } + else { + int res = ptrace(PT_DETACH, pid, 0, 0); + if (res < 0) { + fprintf(stderr, "detach: ptrace(PT_DETACH, %d) failed (%d)\n", pid, res); + } + } + mach_port_deallocate(mach_task_self(), gTask); id symbolicator = getSymbolicator(env, this_obj); if (symbolicator != nil) { @@ -419,10 +591,13 @@ * Method: load_library * Signature: (Ljava/lang/String;)L */ -JNIEXPORT jlong JNICALL Java_sun_jvm_hotspot_asm_Disassembler_load_1library(JNIEnv * env, - jclass disclass, - jstring jrepath_s, - jstring libname_s) { +JNIEXPORT jlong JNICALL +Java_sun_jvm_hotspot_asm_Disassembler_load_1library( + JNIEnv * env, + jclass disclass, + jstring jrepath_s, + jstring libname_s) +{ uintptr_t func = 0; const char* error_message = NULL; const char* java_home; @@ -533,13 +708,16 @@ * Method: decode * Signature: (Lsun/jvm/hotspot/asm/InstructionVisitor;J[BLjava/lang/String;J)V */ -JNIEXPORT void JNICALL Java_sun_jvm_hotspot_asm_Disassembler_decode(JNIEnv * env, - jobject dis, - jobject visitor, - jlong startPc, - jbyteArray code, - jstring options_s, - jlong decode_instructions_virtual) { +JNIEXPORT void JNICALL +Java_sun_jvm_hotspot_asm_Disassembler_decode( + JNIEnv * env, + jobject dis, + jobject visitor, + jlong startPc, + 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); diff -r a413bcd552a4 -r 5fc51c1ecdeb agent/src/os/bsd/libproc_impl.c --- a/agent/src/os/bsd/libproc_impl.c Tue Mar 05 21:58:51 2013 +0100 +++ b/agent/src/os/bsd/libproc_impl.c Tue Mar 05 23:44:54 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -91,6 +91,14 @@ } } +void print_error(const char* format,...) { + va_list alist; + va_start(alist, format); + fputs("ERROR: ", stderr); + vfprintf(stderr, format, alist); + va_end(alist); +} + bool is_debug() { return _libsaproc_debug; } diff -r a413bcd552a4 -r 5fc51c1ecdeb agent/src/os/bsd/libproc_impl.h --- a/agent/src/os/bsd/libproc_impl.h Tue Mar 05 21:58:51 2013 +0100 +++ b/agent/src/os/bsd/libproc_impl.h Tue Mar 05 23:44:54 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -107,6 +107,7 @@ int pathmap_open(const char* name); void print_debug(const char* format,...); +void print_error(const char* format,...); bool is_debug(); typedef bool (*thread_info_callback)(struct ps_prochandle* ph, pthread_t pid, lwpid_t lwpid); diff -r a413bcd552a4 -r 5fc51c1ecdeb agent/src/os/bsd/ps_proc.c --- a/agent/src/os/bsd/ps_proc.c Tue Mar 05 21:58:51 2013 +0100 +++ b/agent/src/os/bsd/ps_proc.c Tue Mar 05 23:44:54 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -129,42 +129,66 @@ return (errno == 0)? true: false; } +static bool ptrace_continue(pid_t pid, int signal) { + // pass the signal to the process so we don't swallow it + if (ptrace(PTRACE_CONT, pid, NULL, signal) < 0) { + print_debug("ptrace(PTRACE_CONT, ..) failed for %d\n", pid); + return false; + } + return true; +} + +// waits until the ATTACH has stopped the process +// by signal SIGSTOP +static bool ptrace_waitpid(pid_t pid) { + int ret; + int status; + do { + // Wait for debuggee to stop. + ret = waitpid(pid, &status, 0); + if (ret >= 0) { + if (WIFSTOPPED(status)) { + // Any signal will stop the thread, make sure it is SIGSTOP. Otherwise SIGSTOP + // will still be pending and delivered when the process is DETACHED and the process + // will go to sleep. + if (WSTOPSIG(status) == SIGSTOP) { + // Debuggee stopped by SIGSTOP. + return true; + } + if (!ptrace_continue(pid, WSTOPSIG(status))) { + print_error("Failed to correctly attach to VM. VM might HANG! [PTRACE_CONT failed, stopped by %d]\n", WSTOPSIG(status)); + return false; + } + } else { + print_debug("waitpid(): Child process exited/terminated (status = 0x%x)\n", status); + return false; + } + } else { + switch (errno) { + case EINTR: + continue; + break; + case ECHILD: + print_debug("waitpid() failed. Child process pid (%d) does not exist \n", pid); + break; + case EINVAL: + print_debug("waitpid() failed. Invalid options argument.\n"); + break; + default: + print_debug("waitpid() failed. Unexpected error %d\n",errno); + } + return false; + } + } while(true); +} + // attach to a process/thread specified by "pid" static bool ptrace_attach(pid_t pid) { if (ptrace(PT_ATTACH, pid, NULL, 0) < 0) { print_debug("ptrace(PTRACE_ATTACH, ..) failed for %d\n", pid); return false; } else { - int ret; - int status; - do { - // Wait for debuggee to stop. - ret = waitpid(pid, &status, 0); - if (ret >= 0) { - if (WIFSTOPPED(status)) { - // Debuggee stopped. - return true; - } else { - print_debug("waitpid(): Child process exited/terminated (status = 0x%x)\n", status); - return false; - } - } else { - switch (errno) { - case EINTR: - continue; - break; - case ECHILD: - print_debug("waitpid() failed. Child process pid (%d) does not exist \n", pid); - break; - case EINVAL: - print_debug("waitpid() failed. Invalid options argument.\n"); - break; - default: - print_debug("waitpid() failed. Unexpected error %d\n",errno); - } - return false; - } - } while(true); + return ptrace_waitpid(pid); } } diff -r a413bcd552a4 -r 5fc51c1ecdeb agent/src/os/linux/LinuxDebuggerLocal.c --- a/agent/src/os/linux/LinuxDebuggerLocal.c Tue Mar 05 21:58:51 2013 +0100 +++ b/agent/src/os/linux/LinuxDebuggerLocal.c Tue Mar 05 23:44:54 2013 +0100 @@ -280,7 +280,7 @@ return (err == PS_OK)? array : 0; } -#if defined(i386) || defined(ia64) || defined(amd64) || defined(sparc) || defined(sparcv9) +#if defined(i386) || defined(amd64) || defined(sparc) || defined(sparcv9) JNIEXPORT jlongArray JNICALL Java_sun_jvm_hotspot_debugger_linux_LinuxDebuggerLocal_getThreadIntegerRegisterSet0 (JNIEnv *env, jobject this_obj, jint lwp_id) { @@ -299,9 +299,6 @@ #ifdef i386 #define NPRGREG sun_jvm_hotspot_debugger_x86_X86ThreadContext_NPRGREG #endif -#ifdef ia64 -#define NPRGREG IA64_REG_COUNT -#endif #ifdef amd64 #define NPRGREG sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext_NPRGREG #endif @@ -336,13 +333,6 @@ #endif /* i386 */ -#if ia64 - regs = (*env)->GetLongArrayElements(env, array, &isCopy); - for (i = 0; i < NPRGREG; i++ ) { - regs[i] = 0xDEADDEAD; - } -#endif /* ia64 */ - #ifdef amd64 #define REG_INDEX(reg) sun_jvm_hotspot_debugger_amd64_AMD64ThreadContext_##reg diff -r a413bcd552a4 -r 5fc51c1ecdeb agent/src/os/linux/libproc.h --- a/agent/src/os/linux/libproc.h Tue Mar 05 21:58:51 2013 +0100 +++ b/agent/src/os/linux/libproc.h Tue Mar 05 23:44:54 2013 +0100 @@ -79,14 +79,6 @@ *************************************************************************************/ -#ifdef ia64 -struct user_regs_struct { -/* copied from user.h which doesn't define this in a struct */ - -#define IA64_REG_COUNT (EF_SIZE/8+32) /* integer and fp regs */ -unsigned long regs[IA64_REG_COUNT]; /* integer and fp regs */ -}; -#endif #if defined(sparc) || defined(sparcv9) #define user_regs_struct pt_regs diff -r a413bcd552a4 -r 5fc51c1ecdeb agent/src/os/linux/libproc_impl.c --- a/agent/src/os/linux/libproc_impl.c Tue Mar 05 21:58:51 2013 +0100 +++ b/agent/src/os/linux/libproc_impl.c Tue Mar 05 23:44:54 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -92,6 +92,14 @@ } } +void print_error(const char* format,...) { + va_list alist; + va_start(alist, format); + fputs("ERROR: ", stderr); + vfprintf(stderr, format, alist); + va_end(alist); +} + bool is_debug() { return _libsaproc_debug; } diff -r a413bcd552a4 -r 5fc51c1ecdeb agent/src/os/linux/libproc_impl.h --- a/agent/src/os/linux/libproc_impl.h Tue Mar 05 21:58:51 2013 +0100 +++ b/agent/src/os/linux/libproc_impl.h Tue Mar 05 23:44:54 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -105,6 +105,7 @@ int pathmap_open(const char* name); void print_debug(const char* format,...); +void print_error(const char* format,...); bool is_debug(); typedef bool (*thread_info_callback)(struct ps_prochandle* ph, pthread_t pid, lwpid_t lwpid); diff -r a413bcd552a4 -r 5fc51c1ecdeb agent/src/os/linux/ps_proc.c --- a/agent/src/os/linux/ps_proc.c Tue Mar 05 21:58:51 2013 +0100 +++ b/agent/src/os/linux/ps_proc.c Tue Mar 05 23:44:54 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include "libproc_impl.h" @@ -142,46 +143,71 @@ } +static bool ptrace_continue(pid_t pid, int signal) { + // pass the signal to the process so we don't swallow it + if (ptrace(PTRACE_CONT, pid, NULL, signal) < 0) { + print_debug("ptrace(PTRACE_CONT, ..) failed for %d\n", pid); + return false; + } + return true; +} + +// waits until the ATTACH has stopped the process +// by signal SIGSTOP +static bool ptrace_waitpid(pid_t pid) { + int ret; + int status; + while (true) { + // Wait for debuggee to stop. + ret = waitpid(pid, &status, 0); + if (ret == -1 && errno == ECHILD) { + // try cloned process. + ret = waitpid(pid, &status, __WALL); + } + if (ret >= 0) { + if (WIFSTOPPED(status)) { + // Any signal will stop the thread, make sure it is SIGSTOP. Otherwise SIGSTOP + // will still be pending and delivered when the process is DETACHED and the process + // will go to sleep. + if (WSTOPSIG(status) == SIGSTOP) { + // Debuggee stopped by SIGSTOP. + return true; + } + if (!ptrace_continue(pid, WSTOPSIG(status))) { + print_error("Failed to correctly attach to VM. VM might HANG! [PTRACE_CONT failed, stopped by %d]\n", WSTOPSIG(status)); + return false; + } + } else { + print_debug("waitpid(): Child process exited/terminated (status = 0x%x)\n", status); + return false; + } + } else { + switch (errno) { + case EINTR: + continue; + break; + case ECHILD: + print_debug("waitpid() failed. Child process pid (%d) does not exist \n", pid); + break; + case EINVAL: + print_debug("waitpid() failed. Invalid options argument.\n"); + break; + default: + print_debug("waitpid() failed. Unexpected error %d\n",errno); + break; + } + return false; + } + } +} + // attach to a process/thread specified by "pid" static bool ptrace_attach(pid_t pid) { if (ptrace(PTRACE_ATTACH, pid, NULL, NULL) < 0) { print_debug("ptrace(PTRACE_ATTACH, ..) failed for %d\n", pid); return false; } else { - int ret; - int status; - do { - // Wait for debuggee to stop. - ret = waitpid(pid, &status, 0); - if (ret == -1 && errno == ECHILD) { - // try cloned process. - ret = waitpid(pid, &status, __WALL); - } - if (ret >= 0) { - if (WIFSTOPPED(status)) { - // Debuggee stopped. - return true; - } else { - print_debug("waitpid(): Child process exited/terminated (status = 0x%x)\n", status); - return false; - } - } else { - switch (errno) { - case EINTR: - continue; - break; - case ECHILD: - print_debug("waitpid() failed. Child process pid (%d) does not exist \n", pid); - break; - case EINVAL: - print_debug("waitpid() failed. Invalid options argument.\n"); - break; - default: - print_debug("waitpid() failed. Unexpected error %d\n",errno); - } - return false; - } - } while(true); + return ptrace_waitpid(pid); } } diff -r a413bcd552a4 -r 5fc51c1ecdeb agent/src/os/win32/windbg/sawindbg.cpp --- a/agent/src/os/win32/windbg/sawindbg.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/agent/src/os/win32/windbg/sawindbg.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -27,10 +27,7 @@ #include "sun_jvm_hotspot_debugger_windbg_WindbgDebuggerLocal.h" -#ifdef _M_IA64 - #include "sun_jvm_hotspot_debugger_ia64_IA64ThreadContext.h" - #define NPRGREG sun_jvm_hotspot_debugger_ia64_IA64ThreadContext_NPRGREG -#elif _M_IX86 +#ifdef _M_IX86 #include "sun_jvm_hotspot_debugger_x86_X86ThreadContext.h" #define NPRGREG sun_jvm_hotspot_debugger_x86_X86ThreadContext_NPRGREG #elif _M_AMD64 @@ -375,8 +372,7 @@ We are attaching to a process in 'read-only' mode. i.e., we do not want to put breakpoints, suspend/resume threads etc. For read-only JDI and HSDB kind of - usage this should suffice. We are not intending to use this for full-fledged - ProcessControl implementation to be used with BugSpotAgent. + usage this should suffice. Please refer to DEBUG_ATTACH_NONINVASIVE mode source comments from dbgeng.h. In this mode, debug engine does not call DebugActiveProrcess. i.e., we are not @@ -491,92 +487,7 @@ memset(&context, 0, sizeof(CONTEXT)); #undef REG_INDEX -#ifdef _M_IA64 - #define REG_INDEX(x) sun_jvm_hotspot_debugger_ia64_IA64ThreadContext_##x - - context.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG; - ptrIDebugAdvanced->GetThreadContext(&context, sizeof(CONTEXT)); - - ptrRegs[REG_INDEX(GR0)] = 0; // always 0 - ptrRegs[REG_INDEX(GR1)] = context.IntGp; // r1 - ptrRegs[REG_INDEX(GR2)] = context.IntT0; // r2-r3 - ptrRegs[REG_INDEX(GR3)] = context.IntT1; - ptrRegs[REG_INDEX(GR4)] = context.IntS0; // r4-r7 - ptrRegs[REG_INDEX(GR5)] = context.IntS1; - ptrRegs[REG_INDEX(GR6)] = context.IntS2; - ptrRegs[REG_INDEX(GR7)] = context.IntS3; - ptrRegs[REG_INDEX(GR8)] = context.IntV0; // r8 - ptrRegs[REG_INDEX(GR9)] = context.IntT2; // r9-r11 - ptrRegs[REG_INDEX(GR10)] = context.IntT3; - ptrRegs[REG_INDEX(GR11)] = context.IntT4; - ptrRegs[REG_INDEX(GR12)] = context.IntSp; // r12 stack pointer - ptrRegs[REG_INDEX(GR13)] = context.IntTeb; // r13 teb - ptrRegs[REG_INDEX(GR14)] = context.IntT5; // r14-r31 - ptrRegs[REG_INDEX(GR15)] = context.IntT6; - ptrRegs[REG_INDEX(GR16)] = context.IntT7; - ptrRegs[REG_INDEX(GR17)] = context.IntT8; - ptrRegs[REG_INDEX(GR18)] = context.IntT9; - ptrRegs[REG_INDEX(GR19)] = context.IntT10; - ptrRegs[REG_INDEX(GR20)] = context.IntT11; - ptrRegs[REG_INDEX(GR21)] = context.IntT12; - ptrRegs[REG_INDEX(GR22)] = context.IntT13; - ptrRegs[REG_INDEX(GR23)] = context.IntT14; - ptrRegs[REG_INDEX(GR24)] = context.IntT15; - ptrRegs[REG_INDEX(GR25)] = context.IntT16; - ptrRegs[REG_INDEX(GR26)] = context.IntT17; - ptrRegs[REG_INDEX(GR27)] = context.IntT18; - ptrRegs[REG_INDEX(GR28)] = context.IntT19; - ptrRegs[REG_INDEX(GR29)] = context.IntT20; - ptrRegs[REG_INDEX(GR30)] = context.IntT21; - ptrRegs[REG_INDEX(GR31)] = context.IntT22; - - ptrRegs[REG_INDEX(INT_NATS)] = context.IntNats; - ptrRegs[REG_INDEX(PREDS)] = context.Preds; - - ptrRegs[REG_INDEX(BR_RP)] = context.BrRp; - ptrRegs[REG_INDEX(BR1)] = context.BrS0; // b1-b5 - ptrRegs[REG_INDEX(BR2)] = context.BrS1; - ptrRegs[REG_INDEX(BR3)] = context.BrS2; - ptrRegs[REG_INDEX(BR4)] = context.BrS3; - ptrRegs[REG_INDEX(BR5)] = context.BrS4; - ptrRegs[REG_INDEX(BR6)] = context.BrT0; // b6-b7 - ptrRegs[REG_INDEX(BR7)] = context.BrT1; - - ptrRegs[REG_INDEX(AP_UNAT)] = context.ApUNAT; - ptrRegs[REG_INDEX(AP_LC)] = context.ApLC; - ptrRegs[REG_INDEX(AP_EC)] = context.ApEC; - ptrRegs[REG_INDEX(AP_CCV)] = context.ApCCV; - ptrRegs[REG_INDEX(AP_DCR)] = context.ApDCR; - - ptrRegs[REG_INDEX(RS_PFS)] = context.RsPFS; - ptrRegs[REG_INDEX(RS_BSP)] = context.RsBSP; - ptrRegs[REG_INDEX(RS_BSPSTORE)] = context.RsBSPSTORE; - ptrRegs[REG_INDEX(RS_RSC)] = context.RsRSC; - ptrRegs[REG_INDEX(RS_RNAT)] = context.RsRNAT; - - ptrRegs[REG_INDEX(ST_IPSR)] = context.StIPSR; - ptrRegs[REG_INDEX(ST_IIP)] = context.StIIP; - ptrRegs[REG_INDEX(ST_IFS)] = context.StIFS; - - ptrRegs[REG_INDEX(DB_I0)] = context.DbI0; - ptrRegs[REG_INDEX(DB_I1)] = context.DbI1; - ptrRegs[REG_INDEX(DB_I2)] = context.DbI2; - ptrRegs[REG_INDEX(DB_I3)] = context.DbI3; - ptrRegs[REG_INDEX(DB_I4)] = context.DbI4; - ptrRegs[REG_INDEX(DB_I5)] = context.DbI5; - ptrRegs[REG_INDEX(DB_I6)] = context.DbI6; - ptrRegs[REG_INDEX(DB_I7)] = context.DbI7; - - ptrRegs[REG_INDEX(DB_D0)] = context.DbD0; - ptrRegs[REG_INDEX(DB_D1)] = context.DbD1; - ptrRegs[REG_INDEX(DB_D2)] = context.DbD2; - ptrRegs[REG_INDEX(DB_D3)] = context.DbD3; - ptrRegs[REG_INDEX(DB_D4)] = context.DbD4; - ptrRegs[REG_INDEX(DB_D5)] = context.DbD5; - ptrRegs[REG_INDEX(DB_D6)] = context.DbD6; - ptrRegs[REG_INDEX(DB_D7)] = context.DbD7; - -#elif _M_IX86 +#ifdef _M_IX86 #define REG_INDEX(x) sun_jvm_hotspot_debugger_x86_X86ThreadContext_##x context.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS; diff -r a413bcd552a4 -r 5fc51c1ecdeb agent/src/share/classes/sun/jvm/hotspot/asm/amd64/AMD64FloatRegister.java --- a/agent/src/share/classes/sun/jvm/hotspot/asm/amd64/AMD64FloatRegister.java Tue Mar 05 21:58:51 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,64 +0,0 @@ -/* - * Copyright (c) 2003, 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 sun.jvm.hotspot.asm.amd64; - -import sun.jvm.hotspot.asm.Register; -import sun.jvm.hotspot.utilities.Assert; - -public class AMD64FloatRegister extends Register { - - public AMD64FloatRegister(int number) { - super(number); - } - - public int getNumber() { - return number; - } - - public int getNumberOfRegisters() { - return AMD64FloatRegisters.getNumRegisters(); - } - - public boolean isFloat() { - return true; - } - - public boolean isFramePointer() { - return false; - } - - public boolean isStackPointer() { - return false; - } - - public boolean isValid() { - return number >= 0 && number < AMD64FloatRegisters.getNumRegisters(); - } - - public String toString() { - return AMD64FloatRegisters.getRegisterName(number); - } - -} diff -r a413bcd552a4 -r 5fc51c1ecdeb agent/src/share/classes/sun/jvm/hotspot/bugspot/BugSpot.java --- a/agent/src/share/classes/sun/jvm/hotspot/bugspot/BugSpot.java Tue Mar 05 21:58:51 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1536 +0,0 @@ -/* - * Copyright (c) 2001, 2012, 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 sun.jvm.hotspot.bugspot; - -import java.awt.*; -import java.awt.event.*; -import java.io.*; -import java.net.*; -import java.util.*; -import javax.swing.*; -import javax.swing.filechooser.*; -import sun.jvm.hotspot.debugger.*; -import sun.jvm.hotspot.debugger.cdbg.*; -import sun.jvm.hotspot.debugger.posix.*; -import sun.jvm.hotspot.debugger.windbg.*; -import sun.jvm.hotspot.livejvm.*; -import sun.jvm.hotspot.memory.*; -import sun.jvm.hotspot.oops.*; -import sun.jvm.hotspot.runtime.*; -import sun.jvm.hotspot.ui.*; -import sun.jvm.hotspot.utilities.*; - -/** The BugSpot component. This is embeddable in an application by - virtue of its being a JComponent. It (currently) requires the use - of a menu bar which can be fetched via getMenuBar(). This is - intended ultimately to replace HSDB. */ - -public class BugSpot extends JPanel { - public BugSpot() { - super(); - Runtime.getRuntime().addShutdownHook(new java.lang.Thread() { - public void run() { - detachDebugger(); - } - }); - } - - /** Turn on or off MDI (Multiple Document Interface) mode. When MDI - is enabled, the BugSpot component contains a JDesktopPane and all - windows are JInternalFrames. When disabled, only the menu bar is - relevant. */ - public void setMDIMode(boolean onOrOff) { - mdiMode = onOrOff; - } - - /** Indicates whether MDI mode is enabled. */ - public boolean getMDIMode() { - return mdiMode; - } - - /** Build user interface widgets. This must be called before adding - the BugSpot component to its parent. */ - public void build() { - setLayout(new BorderLayout()); - - menuBar = new JMenuBar(); - - attachMenuItems = new java.util.ArrayList(); - detachMenuItems = new java.util.ArrayList(); - debugMenuItems = new java.util.ArrayList(); - suspendDebugMenuItems = new java.util.ArrayList(); - resumeDebugMenuItems = new java.util.ArrayList(); - - // - // File menu - // - - JMenu menu = createMenu("File", 'F', 0); - JMenuItem item; - item = createMenuItem("Open source file...", - new ActionListener() { - public void actionPerformed(ActionEvent e) { - openSourceFile(); - } - }, - KeyEvent.VK_O, InputEvent.CTRL_MASK, - 'O', 0); - menu.add(item); - detachMenuItems.add(item); - - menu.addSeparator(); - - item = createMenuItem("Attach to process...", - new ActionListener() { - public void actionPerformed(ActionEvent e) { - showAttachDialog(); - } - }, - 'A', 0); - menu.add(item); - attachMenuItems.add(item); - - item = createMenuItem("Detach", - new ActionListener() { - public void actionPerformed(ActionEvent e) { - detach(); - } - }, - 'D', 0); - menu.add(item); - detachMenuItems.add(item); - - // Disable detach menu items at first - setMenuItemsEnabled(detachMenuItems, false); - - menu.addSeparator(); - - menu.add(createMenuItem("Exit", - new ActionListener() { - public void actionPerformed(ActionEvent e) { - detach(); - System.exit(0); - } - }, - 'x', 1)); - - menuBar.add(menu); - - // - // Debug menu - // - - debugMenu = createMenu("Debug", 'D', 0); - item = createMenuItem("Go", - new ActionListener() { - public void actionPerformed(ActionEvent e) { - if (!attached) return; - if (!isSuspended()) return; - resume(); - } - }, - KeyEvent.VK_F5, 0, - 'G', 0); - debugMenu.add(item); - resumeDebugMenuItems.add(item); - - item = createMenuItem("Break", - new ActionListener() { - public void actionPerformed(ActionEvent e) { - if (!attached) { - System.err.println("Not attached"); - return; - } - if (isSuspended()) { - System.err.println("Already suspended"); - return; - } - suspend(); - } - }, - 'B', 0); - debugMenu.add(item); - suspendDebugMenuItems.add(item); - - debugMenu.addSeparator(); - - item = createMenuItem("Threads...", - new ActionListener() { - public void actionPerformed(ActionEvent e) { - showThreadsDialog(); - } - }, - 'T', 0); - debugMenu.add(item); - debugMenuItems.add(item); - // FIXME: belongs under "View -> Debug Windows" - item = createMenuItem("Memory", - new ActionListener() { - public void actionPerformed(ActionEvent e) { - showMemoryDialog(); - } - }, - 'M', 0); - debugMenu.add(item); - debugMenuItems.add(item); - - debugMenu.setEnabled(false); - menuBar.add(debugMenu); - - if (mdiMode) { - desktop = new JDesktopPane(); - add(desktop, BorderLayout.CENTER); - } - - fixedWidthFont = GraphicsUtilities.lookupFont("Courier"); - - debugEventTimer = new javax.swing.Timer(100, new ActionListener() { - public void actionPerformed(ActionEvent e) { - pollForDebugEvent(); - } - }); - } - - public JMenuBar getMenuBar() { - return menuBar; - } - - public void showAttachDialog() { - setMenuItemsEnabled(attachMenuItems, false); - final FrameWrapper attachDialog = newFrame("Attach to process"); - attachDialog.getContentPane().setLayout(new BorderLayout()); - attachDialog.setClosable(true); - attachDialog.setResizable(true); - - JPanel panel = new JPanel(); - panel.setLayout(new BorderLayout()); - panel.setBorder(GraphicsUtilities.newBorder(5)); - attachDialog.setBackground(panel.getBackground()); - - JPanel listPanel = new JPanel(); - listPanel.setLayout(new BorderLayout()); - final ProcessListPanel plist = new ProcessListPanel(getLocalDebugger()); - panel.add(plist, BorderLayout.CENTER); - JCheckBox check = new JCheckBox("Update list continuously"); - check.addItemListener(new ItemListener() { - public void itemStateChanged(ItemEvent e) { - if (e.getStateChange() == ItemEvent.SELECTED) { - plist.start(); - } else { - plist.stop(); - } - } - }); - listPanel.add(plist, BorderLayout.CENTER); - listPanel.add(check, BorderLayout.SOUTH); - panel.add(listPanel, BorderLayout.CENTER); - attachDialog.getContentPane().add(panel, BorderLayout.CENTER); - attachDialog.setClosingActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - plist.stop(); - setMenuItemsEnabled(attachMenuItems, true); - } - }); - - ActionListener attacher = new ActionListener() { - public void actionPerformed(ActionEvent e) { - plist.stop(); - attachDialog.setVisible(false); - removeFrame(attachDialog); - ProcessInfo info = plist.getSelectedProcess(); - if (info != null) { - attach(info.getPid()); - } - } - }; - - Box hbox = Box.createHorizontalBox(); - hbox.add(Box.createGlue()); - JButton button = new JButton("OK"); - button.addActionListener(attacher); - hbox.add(button); - hbox.add(Box.createHorizontalStrut(20)); - button = new JButton("Cancel"); - button.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - plist.stop(); - attachDialog.setVisible(false); - removeFrame(attachDialog); - setMenuItemsEnabled(attachMenuItems, true); - } - }); - hbox.add(button); - hbox.add(Box.createGlue()); - panel = new JPanel(); - panel.setBorder(GraphicsUtilities.newBorder(5)); - panel.add(hbox); - - attachDialog.getContentPane().add(panel, BorderLayout.SOUTH); - - addFrame(attachDialog); - attachDialog.pack(); - attachDialog.setSize(400, 300); - GraphicsUtilities.centerInContainer(attachDialog.getComponent(), - getParentDimension(attachDialog.getComponent())); - attachDialog.setVisible(true); - } - - public void showThreadsDialog() { - final FrameWrapper threadsDialog = newFrame("Threads"); - threadsDialog.getContentPane().setLayout(new BorderLayout()); - threadsDialog.setClosable(true); - threadsDialog.setResizable(true); - - ThreadListPanel threads = new ThreadListPanel(getCDebugger(), getAgent().isJavaMode()); - threads.addListener(new ThreadListPanel.Listener() { - public void setFocus(ThreadProxy thread, JavaThread jthread) { - setCurrentThread(thread); - // FIXME: print this to GUI, bring some windows to foreground - System.err.println("Focus changed to thread " + thread); - } - }); - threads.setBorder(GraphicsUtilities.newBorder(5)); - threadsDialog.getContentPane().add(threads); - addFrame(threadsDialog); - threadsDialog.pack(); - GraphicsUtilities.reshapeToAspectRatio(threadsDialog.getComponent(), - 3.0f, - 0.9f, - getParentDimension(threadsDialog.getComponent())); - GraphicsUtilities.centerInContainer(threadsDialog.getComponent(), - getParentDimension(threadsDialog.getComponent())); - threadsDialog.setVisible(true); - } - - public void showMemoryDialog() { - final FrameWrapper memoryDialog = newFrame("Memory"); - memoryDialog.getContentPane().setLayout(new BorderLayout()); - memoryDialog.setClosable(true); - memoryDialog.setResizable(true); - - memoryDialog.getContentPane().add(new MemoryViewer(getDebugger(), - (getDebugger().getMachineDescription().getAddressSize() == 8)), - BorderLayout.CENTER); - addFrame(memoryDialog); - memoryDialog.pack(); - GraphicsUtilities.reshapeToAspectRatio(memoryDialog.getComponent(), - 1.0f, - 0.7f, - getParentDimension(memoryDialog.getComponent())); - GraphicsUtilities.centerInContainer(memoryDialog.getComponent(), - getParentDimension(memoryDialog.getComponent())); - memoryDialog.setVisible(true); - } - - /** Changes the editor factory this debugger uses to display source - code. Specified factory may be null, in which case the default - factory is used. */ - public void setEditorFactory(EditorFactory fact) { - if (fact != null) { - editorFact = fact; - } else { - editorFact = new DefaultEditorFactory(); - } - } - - //---------------------------------------------------------------------- - // Internals only below this point - // - - private WorkerThread workerThread; - private boolean mdiMode; - private JVMDebugger localDebugger; - private BugSpotAgent agent = new BugSpotAgent(); - private JMenuBar menuBar; - /** List */ - private java.util.List attachMenuItems; - private java.util.List detachMenuItems; - private java.util.List debugMenuItems; - private java.util.List suspendDebugMenuItems; - private java.util.List resumeDebugMenuItems; - private FrameWrapper stackFrame; - private VariablePanel localsPanel; - private StackTracePanel stackTracePanel; - private FrameWrapper registerFrame; - private RegisterPanel registerPanel; - // Used for mixed-language stack traces - private Map threadToJavaThreadMap; - - private JMenu debugMenu; - - // MDI mode only: desktop pane - private JDesktopPane desktop; - - // Attach/detach state - private boolean attached; - - // Suspension (combined Java/C++) state - private boolean suspended; - - // Fixed-width font - private Font fixedWidthFont; - - // Breakpoint setting - // Maps Strings to List/**/ - private Map sourceFileToLineNumberInfoMap; - // Maps Strings (file names) to Sets of Integers (line numbers) - private Map fileToBreakpointMap; - - // Debug events - private javax.swing.Timer debugEventTimer; - - // Java debug events - private boolean javaEventPending; - - static class BreakpointResult { - private boolean success; - private boolean set; - private int lineNo; - private String why; - - /** For positive results */ - BreakpointResult(boolean success, boolean set, int lineNo) { - this(success, set, lineNo, null); - } - - /** For negative results */ - BreakpointResult(boolean success, boolean set, int lineNo, String why) { - this.success = success; - this.set = set; - this.lineNo = lineNo; - this.why = why; - } - - public boolean succeeded() { - return success; - } - - public boolean set() { - return set; - } - - /** Line at which the breakpoint was actually set; only valid if - succeeded() returns true */ - public int getLine() { - return lineNo; - } - - public String getWhy() { - return why; - } - } - - - // Editors for source code. File name-to-Editor mapping. - private Map editors; - private EditorFactory editorFact = new DefaultEditorFactory(); - private EditorCommands editorComm = new EditorCommands() { - public void windowClosed(Editor editor) { - editors.remove(editor.getSourceFileName()); - } - - public void toggleBreakpointAtLine(Editor editor, int lineNumber) { - // FIXME: handle "lazy" breakpoints where the source file has - // been opened with some other mechanism (File -> Open) and we - // don't have debug information pointing to that file yet - // FIXME: NOT FINISHED - - BreakpointResult res = - handleBreakpointToggle(editor, lineNumber); - if (res.succeeded()) { - if (res.set()) { - editor.showBreakpointAtLine(res.getLine()); - } else { - editor.clearBreakpointAtLine(res.getLine()); - } - } else { - String why = res.getWhy(); - if (why == null) { - why = ""; - } else { - why = ": " + why; - } - showMessageDialog("Unable to toggle breakpoint" + why, - "Unable to toggle breakpoint", - JOptionPane.WARNING_MESSAGE); - } - } - }; - - private void attach(final int pid) { - try { - getAgent().attach(pid); - setMenuItemsEnabled(detachMenuItems, true); - setMenuItemsEnabled(suspendDebugMenuItems, false); - setMenuItemsEnabled(resumeDebugMenuItems, true); - debugMenu.setEnabled(true); - attached = true; - suspended = true; - - if (getAgent().isJavaMode()) { - System.err.println("Java HotSpot(TM) virtual machine detected."); - } else { - System.err.println("(No Java(TM) virtual machine detected)"); - } - - // Set up editor map - editors = new HashMap(); - - // Initialize breakpoints - fileToBreakpointMap = new HashMap(); - - // Create combined stack trace and local variable panel - JPanel framePanel = new JPanel(); - framePanel.setLayout(new BorderLayout()); - framePanel.setBorder(GraphicsUtilities.newBorder(5)); - localsPanel = new VariablePanel(); - JTabbedPane tab = new JTabbedPane(); - tab.addTab("Locals", localsPanel); - tab.setTabPlacement(JTabbedPane.BOTTOM); - framePanel.add(tab, BorderLayout.CENTER); - JPanel stackPanel = new JPanel(); - stackPanel.setLayout(new BoxLayout(stackPanel, BoxLayout.X_AXIS)); - stackPanel.add(new JLabel("Context:")); - stackPanel.add(Box.createHorizontalStrut(5)); - stackTracePanel = new StackTracePanel(); - stackTracePanel.addListener(new StackTracePanel.Listener() { - public void frameChanged(CFrame fr, JavaVFrame jfr) { - setCurrentFrame(fr, jfr); - } - }); - stackPanel.add(stackTracePanel); - framePanel.add(stackPanel, BorderLayout.NORTH); - stackFrame = newFrame("Stack"); - stackFrame.getContentPane().setLayout(new BorderLayout()); - stackFrame.getContentPane().add(framePanel, BorderLayout.CENTER); - stackFrame.setResizable(true); - stackFrame.setClosable(false); - addFrame(stackFrame); - stackFrame.setSize(400, 200); - GraphicsUtilities.moveToInContainer(stackFrame.getComponent(), 0.0f, 1.0f, 0, 20); - stackFrame.setVisible(true); - - // Create register panel - registerPanel = new RegisterPanel(); - registerPanel.setFont(fixedWidthFont); - registerFrame = newFrame("Registers"); - registerFrame.getContentPane().setLayout(new BorderLayout()); - registerFrame.getContentPane().add(registerPanel, BorderLayout.CENTER); - addFrame(registerFrame); - registerFrame.setResizable(true); - registerFrame.setClosable(false); - registerFrame.setSize(225, 200); - GraphicsUtilities.moveToInContainer(registerFrame.getComponent(), - 1.0f, 0.0f, 0, 0); - registerFrame.setVisible(true); - - resetCurrentThread(); - } catch (DebuggerException e) { - final String errMsg = formatMessage(e.getMessage(), 80); - setMenuItemsEnabled(attachMenuItems, true); - showMessageDialog("Unable to connect to process ID " + pid + ":\n\n" + errMsg, - "Unable to Connect", - JOptionPane.WARNING_MESSAGE); - getAgent().detach(); - } - } - - private synchronized void detachDebugger() { - if (!attached) { - return; - } - if (isSuspended()) { - resume(); // Necessary for JVMDI resumption - } - getAgent().detach(); - // FIXME: clear out breakpoints (both Java and C/C++) from target - // process - sourceFileToLineNumberInfoMap = null; - fileToBreakpointMap = null; - threadToJavaThreadMap = null; - editors = null; - attached = false; - } - - private synchronized void detach() { - detachDebugger(); - setMenuItemsEnabled(attachMenuItems, true); - setMenuItemsEnabled(detachMenuItems, false); - debugMenu.setEnabled(false); - if (mdiMode) { - // FIXME: is this sufficient, or will I have to do anything else - // to the components to kill them off? What about WorkerThreads? - desktop.removeAll(); - desktop.invalidate(); - desktop.validate(); - desktop.repaint(); - } - // FIXME: keep track of all windows and close them even in non-MDI - // mode - debugEventTimer.stop(); - } - - // Returns a Debugger for processes on the local machine. This is - // only used to fetch the process list. - private Debugger getLocalDebugger() { - if (localDebugger == null) { - String os = PlatformInfo.getOS(); - String cpu = PlatformInfo.getCPU(); - - if (os.equals("win32")) { - if (!cpu.equals("x86")) { - throw new DebuggerException("Unsupported CPU \"" + cpu + "\" for Windows"); - } - - localDebugger = new WindbgDebuggerLocal(new MachineDescriptionIntelX86(), true); - } else if (os.equals("linux")) { - if (!cpu.equals("x86")) { - throw new DebuggerException("Unsupported CPU \"" + cpu + "\" for Linux"); - } - - // FIXME: figure out how to specify path to debugger module - throw new RuntimeException("FIXME: figure out how to specify path to debugger module"); - // localDebugger = new PosixDebuggerLocal(new MachineDescriptionIntelX86(), true); - } else { - // FIXME: port to Solaris - throw new DebuggerException("Unsupported OS \"" + os + "\""); - } - - // FIXME: we require that the primitive type sizes be configured - // in order to use basic functionality in class Address such as - // the fetching of floating-point values. There are a lot of - // assumptions in the current code that Java floats and doubles - // are of equivalent size to C values. The configurability of the - // primitive type sizes hasn't seemed necessary and in this kind - // of debugging scenario (namely, debugging arbitrary C++ - // processes) it appears difficult to support that kind of - // flexibility. - localDebugger.configureJavaPrimitiveTypeSizes(1, 1, 2, 8, 4, 4, 8, 2); - } - - return localDebugger; - } - - private BugSpotAgent getAgent() { - return agent; - } - - private Debugger getDebugger() { - return getAgent().getDebugger(); - } - - private CDebugger getCDebugger() { - return getAgent().getCDebugger(); - } - - private void resetCurrentThread() { - setCurrentThread((ThreadProxy) getCDebugger().getThreadList().get(0)); - } - - private void setCurrentThread(ThreadProxy t) { - // Create stack trace - // FIXME: add ability to intermix C/Java frames - java.util.List trace = new ArrayList(); - CFrame fr = getCDebugger().topFrameForThread(t); - while (fr != null) { - trace.add(new StackTraceEntry(fr, getCDebugger())); - try { - fr = fr.sender(t); - } catch (AddressException e) { - e.printStackTrace(); - showMessageDialog("Error while walking stack; stack trace will be truncated\n(see console for details)", - "Error walking stack", - JOptionPane.WARNING_MESSAGE); - fr = null; - } - } - JavaThread jthread = javaThreadForProxy(t); - if (jthread != null) { - // Java mode, and we have a Java thread. - // Find all Java frames on the stack. We currently do this in a - // manner which involves minimal interaction between the Java - // and C/C++ debugging systems: any C frame which has a PC in an - // unknown location (i.e., not in any DSO) is assumed to be a - // Java frame. We merge stack segments of unknown frames with - // segments of Java frames beginning with native methods. - java.util.List javaTrace = new ArrayList(); - VFrame vf = jthread.getLastJavaVFrameDbg(); - while (vf != null) { - if (vf.isJavaFrame()) { - javaTrace.add(new StackTraceEntry((JavaVFrame) vf)); - vf = vf.sender(); - } - } - // Merge stack traces - java.util.List mergedTrace = new ArrayList(); - int c = 0; - int j = 0; - while (c < trace.size()) { - StackTraceEntry entry = (StackTraceEntry) trace.get(c); - if (entry.isUnknownCFrame()) { - boolean gotJavaFrame = false; - while (j < javaTrace.size()) { - StackTraceEntry javaEntry = (StackTraceEntry) javaTrace.get(j); - JavaVFrame jvf = javaEntry.getJavaFrame(); - Method m = jvf.getMethod(); - if (!m.isNative() || !gotJavaFrame) { - gotJavaFrame = true; - mergedTrace.add(javaEntry); - ++j; - } else { - break; // Reached native method; have intervening C frames - } - } - if (gotJavaFrame) { - // Skip this sequence of unknown frames, as we've - // successfully identified it as Java frames - while (c < trace.size() && entry.isUnknownCFrame()) { - ++c; - if (c < trace.size()) { - entry = (StackTraceEntry) trace.get(c); - } - } - continue; - } - } - // If we get here, we either have an unknown frame we didn't - // know how to categorize or we have a known C frame. Add it - // to the trace. - mergedTrace.add(entry); - ++c; - } - trace = mergedTrace; - } - stackTracePanel.setTrace(trace); - - registerPanel.update(t); - } - - private void setCurrentFrame(CFrame fr, JavaVFrame jfr) { - localsPanel.clear(); - - if (fr != null) { - localsPanel.update(fr); - - // FIXME: load source file if we can find it, otherwise display disassembly - LoadObject lo = getCDebugger().loadObjectContainingPC(fr.pc()); - if (lo != null) { - CDebugInfoDataBase db = lo.getDebugInfoDataBase(); - if (db != null) { - LineNumberInfo info = db.lineNumberForPC(fr.pc()); - if (info != null) { - System.err.println("PC " + fr.pc() + ": Source file \"" + - info.getSourceFileName() + - "\", line number " + - info.getLineNumber() + - ", PC range [" + - info.getStartPC() + - ", " + - info.getEndPC() + - ")"); - // OK, here we go... - showLineNumber(null, info.getSourceFileName(), info.getLineNumber()); - } else { - System.err.println("(No line number information for PC " + fr.pc() + ")"); - // Dump line number information for database - db.iterate(new LineNumberVisitor() { - public void doLineNumber(LineNumberInfo info) { - System.err.println(" Source file \"" + - info.getSourceFileName() + - "\", line number " + - info.getLineNumber() + - ", PC range [" + - info.getStartPC() + - ", " + - info.getEndPC() + - ")"); - } - }); - } - } - } - } else { - if (Assert.ASSERTS_ENABLED) { - Assert.that(jfr != null, "Must have either C or Java frame"); - } - localsPanel.update(jfr); - // See whether we can locate source file and line number - // FIXME: infer pathmap entries from user's locating of this - // source file - // FIXME: figure out what to do for native methods. Possible to - // go to line number for the native method declaration? - Method m = jfr.getMethod(); - Symbol sfn = ((InstanceKlass) m.getMethodHolder()).getSourceFileName(); - if (sfn != null) { - int bci = jfr.getBCI(); - int lineNo = m.getLineNumberFromBCI(bci); - if (lineNo >= 0) { - // FIXME: show disassembly otherwise - showLineNumber(packageName(m.getMethodHolder().getName().asString()), - sfn.asString(), lineNo); - } - } - } - } - - private String packageName(String str) { - int idx = str.lastIndexOf('/'); - if (idx < 0) { - return ""; - } - return str.substring(0, idx).replace('/', '.'); - } - - private JavaThread javaThreadForProxy(ThreadProxy t) { - if (!getAgent().isJavaMode()) { - return null; - } - if (threadToJavaThreadMap == null) { - threadToJavaThreadMap = new HashMap(); - Threads threads = VM.getVM().getThreads(); - for (JavaThread thr = threads.first(); thr != null; thr = thr.next()) { - threadToJavaThreadMap.put(thr.getThreadProxy(), thr); - } - } - return (JavaThread) threadToJavaThreadMap.get(t); - } - - private static JMenu createMenu(String name, char mnemonic, int mnemonicPos) { - JMenu menu = new JMenu(name); - menu.setMnemonic(mnemonic); - menu.setDisplayedMnemonicIndex(mnemonicPos); - return menu; - } - - private static JMenuItem createMenuItem(String name, ActionListener l) { - JMenuItem item = new JMenuItem(name); - item.addActionListener(l); - return item; - } - - private static JMenuItem createMenuItemInternal(String name, ActionListener l, int accelerator, int modifiers) { - JMenuItem item = createMenuItem(name, l); - item.setAccelerator(KeyStroke.getKeyStroke(accelerator, modifiers)); - return item; - } - - private static JMenuItem createMenuItem(String name, ActionListener l, int accelerator) { - return createMenuItemInternal(name, l, accelerator, 0); - } - - private static JMenuItem createMenuItem(String name, ActionListener l, char mnemonic, int mnemonicPos) { - JMenuItem item = createMenuItem(name, l); - item.setMnemonic(mnemonic); - item.setDisplayedMnemonicIndex(mnemonicPos); - return item; - } - - private static JMenuItem createMenuItem(String name, - ActionListener l, - int accelerator, - int acceleratorMods, - char mnemonic, - int mnemonicPos) { - JMenuItem item = createMenuItemInternal(name, l, accelerator, acceleratorMods); - item.setMnemonic(mnemonic); - item.setDisplayedMnemonicIndex(mnemonicPos); - return item; - } - - /** Punctuates the given string with \n's where necessary to not - exceed the given number of characters per line. Strips - extraneous whitespace. */ - private static String formatMessage(String message, int charsPerLine) { - StringBuffer buf = new StringBuffer(message.length()); - StringTokenizer tokenizer = new StringTokenizer(message); - int curLineLength = 0; - while (tokenizer.hasMoreTokens()) { - String tok = tokenizer.nextToken(); - if (curLineLength + tok.length() > charsPerLine) { - buf.append('\n'); - curLineLength = 0; - } else { - if (curLineLength != 0) { - buf.append(' '); - ++curLineLength; - } - } - buf.append(tok); - curLineLength += tok.length(); - } - return buf.toString(); - } - - private void setMenuItemsEnabled(java.util.List items, boolean enabled) { - for (Iterator iter = items.iterator(); iter.hasNext(); ) { - ((JMenuItem) iter.next()).setEnabled(enabled); - } - } - - private void showMessageDialog(final String message, final String title, final int jOptionPaneKind) { - SwingUtilities.invokeLater(new Runnable() { - public void run() { - if (mdiMode) { - JOptionPane.showInternalMessageDialog(desktop, message, title, jOptionPaneKind); - } else { - JOptionPane.showMessageDialog(null, message, title, jOptionPaneKind); - } - } - }); - } - - private FrameWrapper newFrame(String title) { - if (mdiMode) { - return new JInternalFrameWrapper(new JInternalFrame(title)); - } else { - return new JFrameWrapper(new JFrame(title)); - } - } - - private void addFrame(FrameWrapper frame) { - if (mdiMode) { - desktop.add(frame.getComponent()); - } - } - - private void removeFrame(FrameWrapper frame) { - if (mdiMode) { - desktop.remove(frame.getComponent()); - desktop.invalidate(); - desktop.validate(); - desktop.repaint(); - } - // FIXME: do something when not in MDI mode - } - - private Dimension getParentDimension(Component c) { - if (mdiMode) { - return desktop.getSize(); - } else { - return Toolkit.getDefaultToolkit().getScreenSize(); - } - } - - // Default editor implementation - class DefaultEditor implements Editor { - private DefaultEditorFactory factory; - private FrameWrapper editorFrame; - private String filename; - private SourceCodePanel code; - private boolean shown; - private Object userData; - - public DefaultEditor(DefaultEditorFactory fact, String filename, final EditorCommands comm) { - this.filename = filename; - this.factory = fact; - editorFrame = newFrame(filename); - code = new SourceCodePanel(); - // FIXME: when font changes, change font in editors as well - code.setFont(fixedWidthFont); - editorFrame.getContentPane().add(code); - editorFrame.setClosable(true); - editorFrame.setResizable(true); - editorFrame.setClosingActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - comm.windowClosed(DefaultEditor.this); - removeFrame(editorFrame); - editorFrame.dispose(); - factory.editorClosed(DefaultEditor.this); - } - }); - editorFrame.setActivatedActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - factory.makeEditorCurrent(DefaultEditor.this); - code.requestFocus(); - } - }); - code.setEditorCommands(comm, this); - } - - public boolean openFile() { return code.openFile(filename); } - public String getSourceFileName() { return filename; } - public int getCurrentLineNumber() { return code.getCurrentLineNumber(); } - public void showLineNumber(int lineNo) { - if (!shown) { - addFrame(editorFrame); - GraphicsUtilities.reshapeToAspectRatio(editorFrame.getComponent(), - 1.0f, - 0.85f, - getParentDimension(editorFrame.getComponent())); - editorFrame.setVisible(true); - shown = true; - } - code.showLineNumber(lineNo); - editorFrame.toFront(); - } - public void highlightLineNumber(int lineNo) { code.highlightLineNumber(lineNo); } - public void showBreakpointAtLine(int lineNo) { code.showBreakpointAtLine(lineNo); } - public boolean hasBreakpointAtLine(int lineNo) { return code.hasBreakpointAtLine(lineNo); } - public void clearBreakpointAtLine(int lineNo) { code.clearBreakpointAtLine(lineNo); } - public void clearBreakpoints() { code.clearBreakpoints(); } - public void setUserData(Object o) { userData = o; } - public Object getUserData() { return userData; } - public void toFront() { editorFrame.toFront(); - factory.makeEditorCurrent(this); } - } - - class DefaultEditorFactory implements EditorFactory { - private LinkedList/**/ editors = new LinkedList(); - - public Editor openFile(String filename, EditorCommands commands) { - DefaultEditor editor = new DefaultEditor(this, filename, editorComm); - if (!editor.openFile()) { - return null; - } - return editor; - } - - public Editor getCurrentEditor() { - if (editors.isEmpty()) { - return null; - } - return (Editor) editors.getFirst(); - } - - void editorClosed(Editor editor) { - editors.remove(editor); - } - - void makeEditorCurrent(Editor editor) { - editors.remove(editor); - editors.addFirst(editor); - } - } - - // Helper class for loading .java files; show only those with - // correct file name which are also in the correct package - static class JavaFileFilter extends javax.swing.filechooser.FileFilter { - private String packageName; - private String fileName; - - JavaFileFilter(String packageName, String fileName) { - this.packageName = packageName; - this.fileName = fileName; - } - - public boolean accept(File f) { - if (f.isDirectory()) { - return true; - } - // This rejects most files - if (!f.getName().equals(fileName)) { - return false; - } - // Ensure selected file is in the correct package - PackageScanner scanner = new PackageScanner(); - String pkg = scanner.scan(f); - if (!pkg.equals(packageName)) { - return false; - } - return true; - } - - public String getDescription() { return "Java source files"; } - } - - // Auxiliary information used only for Java source files - static class JavaUserData { - private String packageName; // External format - private String sourceFileName; - - /** Source file name is equivalent to that found in the .java - file; i.e., not a full path */ - JavaUserData(String packageName, String sourceFileName) { - this.packageName = packageName; - this.sourceFileName = sourceFileName; - } - - String packageName() { return packageName; } - String sourceFileName() { return sourceFileName; } - } - - // Opens a source file. This makes it available for the setting of - // lazy breakpoints. - private void openSourceFile() { - JFileChooser chooser = new JFileChooser(); - chooser.setDialogTitle("Open source code file"); - chooser.setMultiSelectionEnabled(false); - if (chooser.showOpenDialog(null) != JFileChooser.APPROVE_OPTION) { - return; - } - File chosen = chooser.getSelectedFile(); - if (chosen == null) { - return; - } - - // See whether we have a Java source file. If so, derive a package - // name for it. - String path = chosen.getPath(); - String name = null; - JavaUserData data = null; - if (path.endsWith(".java")) { - PackageScanner scanner = new PackageScanner(); - String pkg = scanner.scan(chosen); - // Now knowing both the package name and file name, we can put - // this in the editor map and use it for setting breakpoints - // later - String fileName = chosen.getName(); - name = pkg + "." + fileName; - data = new JavaUserData(pkg, fileName); - } else { - // FIXME: need pathmap mechanism - name = path; - } - Editor editor = (Editor) editors.get(name); - if (editor == null) { - editor = editorFact.openFile(path, editorComm); - if (editor == null) { - showMessageDialog("Unable to open file \"" + path + "\" -- unexpected error.", - "Unable to open file", - JOptionPane.WARNING_MESSAGE); - return; - } - editors.put(name, editor); - if (data != null) { - editor.setUserData(data); - } - } else { - editor.toFront(); - } - editor.showLineNumber(1); - // Show breakpoints as well if we have any for this file - Set set = (Set) fileToBreakpointMap.get(editor.getSourceFileName()); - if (set != null) { - for (Iterator iter = set.iterator(); iter.hasNext(); ) { - editor.showBreakpointAtLine(((Integer) iter.next()).intValue()); - } - } - } - - // Package name may be null, in which case the file is assumed to be - // a C source file. Otherwise it is assumed to be a Java source file - // and certain filtering rules will be applied. - private void showLineNumber(String packageName, String fileName, int lineNumber) { - String name; - if (packageName == null) { - name = fileName; - } else { - name = packageName + "." + fileName; - } - Editor editor = (Editor) editors.get(name); - if (editor == null) { - // See whether file exists - File file = new File(fileName); - String realFileName = fileName; - if (!file.exists()) { - // User must specify path to file - JFileChooser chooser = new JFileChooser(); - chooser.setDialogTitle("Please locate " + fileName); - chooser.setMultiSelectionEnabled(false); - if (packageName != null) { - chooser.setFileFilter(new JavaFileFilter(packageName, fileName)); - } - int res = chooser.showOpenDialog(null); - if (res != JFileChooser.APPROVE_OPTION) { - // FIXME: show disassembly instead - return; - } - // FIXME: would like to infer more from the selection; i.e., - // a pathmap leading up to this file - File chosen = chooser.getSelectedFile(); - if (chosen == null) { - return; - } - realFileName = chosen.getPath(); - } - // Now instruct editor factory to open file - editor = editorFact.openFile(realFileName, editorComm); - if (editor == null) { - showMessageDialog("Unable to open file \"" + realFileName + "\" -- unexpected error.", - "Unable to open file", - JOptionPane.WARNING_MESSAGE); - return; - } - // Got an editor; put it in map - editors.put(name, editor); - // If Java source file, add additional information for later - if (packageName != null) { - editor.setUserData(new JavaUserData(packageName, fileName)); - } - } - // Got editor; show line - editor.showLineNumber(lineNumber); - editor.highlightLineNumber(lineNumber); - // Show breakpoints as well if we have any for this file - Set set = (Set) fileToBreakpointMap.get(editor.getSourceFileName()); - if (set != null) { - for (Iterator iter = set.iterator(); iter.hasNext(); ) { - editor.showBreakpointAtLine(((Integer) iter.next()).intValue()); - } - } - } - - // - // Suspend/resume - // - - private boolean isSuspended() { - return suspended; - } - - private synchronized void suspend() { - setMenuItemsEnabled(resumeDebugMenuItems, true); - setMenuItemsEnabled(suspendDebugMenuItems, false); - BugSpotAgent agent = getAgent(); - if (agent.canInteractWithJava() && !agent.isJavaSuspended()) { - agent.suspendJava(); - } - agent.suspend(); - // FIXME: call VM.getVM().fireVMSuspended() - resetCurrentThread(); - debugEventTimer.stop(); - suspended = true; - } - - private synchronized void resume() { - // Note: we don't wipe out the cached state like the - // sourceFileToLineNumberInfoMap since it is too expensive to - // recompute. Instead we recompute it if any DLLs are loaded or - // unloaded. - threadToJavaThreadMap = null; - setMenuItemsEnabled(resumeDebugMenuItems, false); - setMenuItemsEnabled(suspendDebugMenuItems, true); - registerPanel.clear(); - // FIXME: call VM.getVM().fireVMResumed() - BugSpotAgent agent = getAgent(); - agent.resume(); - if (agent.canInteractWithJava()) { - if (agent.isJavaSuspended()) { - agent.resumeJava(); - } - if (javaEventPending) { - javaEventPending = false; - // Clear it out before resuming polling for events - agent.javaEventContinue(); - } - } - agent.enableJavaInteraction(); - suspended = false; - debugEventTimer.start(); - } - - // - // Breakpoints - // - - private synchronized BreakpointResult handleBreakpointToggle(Editor editor, int lineNumber) { - // Currently we only use user data in editors to indicate Java - // source files. If this changes then this code will need to - // change. - JavaUserData data = (JavaUserData) editor.getUserData(); - String filename = editor.getSourceFileName(); - if (data == null) { - // C/C++ code - // FIXME: as noted above in EditorCommands.toggleBreakpointAtLine, - // this needs more work to handle "lazy" breakpoints in files - // which we don't know about in the debug information yet - CDebugger dbg = getCDebugger(); - ProcessControl prctl = dbg.getProcessControl(); - if (prctl == null) { - return new BreakpointResult(false, false, 0, "Process control not enabled"); - } - boolean mustSuspendAndResume = (!prctl.isSuspended()); - try { - if (mustSuspendAndResume) { - prctl.suspend(); - } - // Search debug info for all DSOs - LineNumberInfo info = getLineNumberInfo(filename, lineNumber); - if (info != null) { - Set bpset = (Set) fileToBreakpointMap.get(filename); - if (bpset == null) { - bpset = new HashSet(); - fileToBreakpointMap.put(filename, bpset); - } - Integer key = new Integer(info.getLineNumber()); - if (bpset.contains(key)) { - // Clear breakpoint at this line's PC - prctl.clearBreakpoint(info.getStartPC()); - bpset.remove(key); - return new BreakpointResult(true, false, info.getLineNumber()); - } else { - // Set breakpoint at this line's PC - System.err.println("Setting breakpoint at PC " + info.getStartPC()); - prctl.setBreakpoint(info.getStartPC()); - bpset.add(key); - return new BreakpointResult(true, true, info.getLineNumber()); - } - } else { - return new BreakpointResult(false, false, 0, "No debug information for this source file and line"); - } - } finally { - if (mustSuspendAndResume) { - prctl.resume(); - } - } - } else { - BugSpotAgent agent = getAgent(); - if (!agent.canInteractWithJava()) { - String why; - if (agent.isJavaInteractionDisabled()) { - why = "Can not toggle Java breakpoints while stopped because\nof C/C++ debug events (breakpoints, single-stepping)"; - } else { - why = "Could not talk to SA's JVMDI module to enable Java\nprogramming language breakpoints (run with -Xdebug -Xrunsa)"; - } - return new BreakpointResult(false, false, 0, why); - } - Set bpset = (Set) fileToBreakpointMap.get(filename); - if (bpset == null) { - bpset = new HashSet(); - fileToBreakpointMap.put(filename, bpset); - } - boolean mustResumeAndSuspend = isSuspended(); - try { - if (mustResumeAndSuspend) { - agent.resume(); - } - ServiceabilityAgentJVMDIModule.BreakpointToggleResult res = - getAgent().toggleJavaBreakpoint(data.sourceFileName(), - data.packageName(), - lineNumber); - if (res.getSuccess()) { - Integer key = new Integer(res.getLineNumber()); - boolean addRemRes = false; - if (res.getWasSet()) { - addRemRes = bpset.add(key); - System.err.println("Setting breakpoint at " + res.getMethodName() + res.getMethodSignature() + - ", bci " + res.getBCI() + ", line " + res.getLineNumber()); - } else { - addRemRes = bpset.remove(key); - System.err.println("Clearing breakpoint at " + res.getMethodName() + res.getMethodSignature() + - ", bci " + res.getBCI() + ", line " + res.getLineNumber()); - } - if (Assert.ASSERTS_ENABLED) { - Assert.that(addRemRes, "Inconsistent Java breakpoint state with respect to target process"); - } - return new BreakpointResult(true, res.getWasSet(), res.getLineNumber()); - } else { - return new BreakpointResult(false, false, 0, res.getErrMsg()); - } - } finally { - if (mustResumeAndSuspend) { - agent.suspend(); - resetCurrentThread(); - } - } - } - } - - // Must call only when suspended - private LineNumberInfo getLineNumberInfo(String filename, int lineNumber) { - Map map = getSourceFileToLineNumberInfoMap(); - java.util.List infos = (java.util.List) map.get(filename); - if (infos == null) { - return null; - } - // Binary search for line number - return searchLineNumbers(infos, lineNumber, 0, infos.size()); - } - - // Must call only when suspended - private Map getSourceFileToLineNumberInfoMap() { - if (sourceFileToLineNumberInfoMap == null) { - // Build from debug info - java.util.List loadObjects = getCDebugger().getLoadObjectList(); - final Map map = new HashMap(); - for (Iterator iter = loadObjects.iterator(); iter.hasNext(); ) { - LoadObject lo = (LoadObject) iter.next(); - CDebugInfoDataBase db = lo.getDebugInfoDataBase(); - if (db != null) { - db.iterate(new LineNumberVisitor() { - public void doLineNumber(LineNumberInfo info) { - String name = info.getSourceFileName(); - if (name != null) { - java.util.List val = (java.util.List) map.get(name); - if (val == null) { - val = new ArrayList(); - map.put(name, val); - } - val.add(info); - } - } - }); - } - } - // Sort all lists - for (Iterator iter = map.values().iterator(); iter.hasNext(); ) { - java.util.List list = (java.util.List) iter.next(); - Collections.sort(list, new Comparator() { - public int compare(Object o1, Object o2) { - LineNumberInfo l1 = (LineNumberInfo) o1; - LineNumberInfo l2 = (LineNumberInfo) o2; - int n1 = l1.getLineNumber(); - int n2 = l2.getLineNumber(); - if (n1 < n2) return -1; - if (n1 == n2) return 0; - return 1; - } - }); - } - sourceFileToLineNumberInfoMap = map; - } - return sourceFileToLineNumberInfoMap; - } - - private LineNumberInfo searchLineNumbers(java.util.List infoList, int lineNo, int lowIdx, int highIdx) { - if (highIdx < lowIdx) return null; - if (lowIdx == highIdx) { - // Base case: see whether start PC is less than or equal to addr - if (checkLineNumber(infoList, lineNo, lowIdx)) { - return (LineNumberInfo) infoList.get(lowIdx); - } else { - return null; - } - } else if (lowIdx == highIdx - 1) { - if (checkLineNumber(infoList, lineNo, lowIdx)) { - return (LineNumberInfo) infoList.get(lowIdx); - } else if (checkLineNumber(infoList, lineNo, highIdx)) { - return (LineNumberInfo) infoList.get(highIdx); - } else { - return null; - } - } - int midIdx = (lowIdx + highIdx) >> 1; - LineNumberInfo info = (LineNumberInfo) infoList.get(midIdx); - if (lineNo < info.getLineNumber()) { - // Always move search down - return searchLineNumbers(infoList, lineNo, lowIdx, midIdx); - } else if (lineNo == info.getLineNumber()) { - return info; - } else { - // Move search up - return searchLineNumbers(infoList, lineNo, midIdx, highIdx); - } - } - - private boolean checkLineNumber(java.util.List infoList, int lineNo, int idx) { - LineNumberInfo info = (LineNumberInfo) infoList.get(idx); - return (info.getLineNumber() >= lineNo); - } - - // - // Debug events - // - - private synchronized void pollForDebugEvent() { - ProcessControl prctl = getCDebugger().getProcessControl(); - if (prctl == null) { - return; - } - DebugEvent ev = prctl.debugEventPoll(); - if (ev != null) { - DebugEvent.Type t = ev.getType(); - if (t == DebugEvent.Type.LOADOBJECT_LOAD || - t == DebugEvent.Type.LOADOBJECT_UNLOAD) { - // Conservatively clear cached debug info state - sourceFileToLineNumberInfoMap = null; - // FIXME: would be very useful to have "stop on load/unload" - // events - // FIXME: must do work at these events to implement lazy - // breakpoints - prctl.debugEventContinue(); - } else if (t == DebugEvent.Type.BREAKPOINT) { - // Note: Visual C++ only notifies on breakpoints it doesn't - // know about - - // FIXME: put back test - // if (!prctl.isBreakpointSet(ev.getPC())) { - showMessageDialog("Breakpoint reached at PC " + ev.getPC(), - "Breakpoint reached", - JOptionPane.INFORMATION_MESSAGE); - // } - agent.disableJavaInteraction(); - suspend(); - prctl.debugEventContinue(); - } else if (t == DebugEvent.Type.SINGLE_STEP) { - agent.disableJavaInteraction(); - suspend(); - prctl.debugEventContinue(); - } else if (t == DebugEvent.Type.ACCESS_VIOLATION) { - showMessageDialog("Access violation attempting to " + - (ev.getWasWrite() ? "write" : "read") + - " address " + ev.getAddress() + - " at PC " + ev.getPC(), - "Access Violation", - JOptionPane.WARNING_MESSAGE); - agent.disableJavaInteraction(); - suspend(); - prctl.debugEventContinue(); - } else { - String info = "Unknown debug event encountered"; - if (ev.getUnknownEventDetail() != null) { - info = info + ": " + ev.getUnknownEventDetail(); - } - showMessageDialog(info, "Unknown debug event", JOptionPane.INFORMATION_MESSAGE); - suspend(); - prctl.debugEventContinue(); - } - return; - } - - // No C++ debug event; poll for Java debug event - if (getAgent().canInteractWithJava()) { - if (!javaEventPending) { - if (getAgent().javaEventPending()) { - suspend(); - // This does a lot of work and we want to have the page - // cache available to us as it runs - sun.jvm.hotspot.livejvm.Event jev = getAgent().javaEventPoll(); - if (jev != null) { - javaEventPending = true; - if (jev.getType() == sun.jvm.hotspot.livejvm.Event.Type.BREAKPOINT) { - BreakpointEvent bpev = (BreakpointEvent) jev; - showMessageDialog("Breakpoint reached in method\n" + - bpev.methodID().method().externalNameAndSignature() + - ",\nbci " + bpev.location(), - "Breakpoint reached", - JOptionPane.INFORMATION_MESSAGE); - } else if (jev.getType() == sun.jvm.hotspot.livejvm.Event.Type.EXCEPTION) { - ExceptionEvent exev = (ExceptionEvent) jev; - showMessageDialog(exev.exception().getKlass().getName().asString() + - "\nthrown in method\n" + - exev.methodID().method().externalNameAndSignature() + - "\nat BCI " + exev.location(), - "Exception thrown", - JOptionPane.INFORMATION_MESSAGE); - } else { - Assert.that(false, "Should not reach here"); - } - } - } - } - } - } -} diff -r a413bcd552a4 -r 5fc51c1ecdeb agent/src/share/classes/sun/jvm/hotspot/bugspot/BugSpotAgent.java --- a/agent/src/share/classes/sun/jvm/hotspot/bugspot/BugSpotAgent.java Tue Mar 05 21:58:51 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,799 +0,0 @@ -/* - * Copyright (c) 2002, 2012, 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 sun.jvm.hotspot.bugspot; - -import java.io.PrintStream; -import java.net.*; -import java.rmi.*; -import sun.jvm.hotspot.*; -import sun.jvm.hotspot.debugger.*; -import sun.jvm.hotspot.debugger.bsd.*; -import sun.jvm.hotspot.debugger.proc.*; -import sun.jvm.hotspot.debugger.cdbg.*; -import sun.jvm.hotspot.debugger.windbg.*; -import sun.jvm.hotspot.debugger.linux.*; -import sun.jvm.hotspot.debugger.sparc.*; -import sun.jvm.hotspot.debugger.remote.*; -import sun.jvm.hotspot.livejvm.*; -import sun.jvm.hotspot.memory.*; -import sun.jvm.hotspot.oops.*; -import sun.jvm.hotspot.runtime.*; -import sun.jvm.hotspot.types.*; -import sun.jvm.hotspot.utilities.*; - -/**

This class wraps the basic functionality for connecting to the - * target process or debug server. It makes it simple to start up the - * debugging system.

- * - *

This agent (as compared to the HotSpotAgent) can connect to - * and interact with arbitrary processes. If the target process - * happens to be a HotSpot JVM, the Java debugging features of the - * Serviceability Agent are enabled. Further, if the Serviceability - * Agent's JVMDI module is loaded into the target VM, interaction - * with the live Java program is possible, specifically the catching - * of exceptions and setting of breakpoints.

- * - *

The BugSpot debugger requires that the underlying Debugger - * support C/C++ debugging via the CDebugger interface.

- * - *

FIXME: especially with the addition of remote debugging, this - * has turned into a mess; needs rethinking.

*/ - -public class BugSpotAgent { - - private JVMDebugger debugger; - private MachineDescription machDesc; - private TypeDataBase db; - - private String os; - private String cpu; - private String fileSep; - - // The system can work in several ways: - // - Attaching to local process - // - Attaching to local core file - // - Connecting to remote debug server - // - Starting debug server for process - // - Starting debug server for core file - - // These are options for the "client" side of things - private static final int PROCESS_MODE = 0; - private static final int CORE_FILE_MODE = 1; - private static final int REMOTE_MODE = 2; - private int startupMode; - - // This indicates whether we are really starting a server or not - private boolean isServer; - - // All possible required information for connecting - private int pid; - private String executableName; - private String coreFileName; - private String debugServerID; - - // All needed information for server side - private String serverID; - - // Indicates whether we are attached to a HotSpot JVM or not - private boolean javaMode; - - // Indicates whether we have process control over a live HotSpot JVM - // or not; non-null if so. - private ServiceabilityAgentJVMDIModule jvmdi; - // While handling C breakpoints interactivity with the Java program - // is forbidden. Too many invariants are broken while the target is - // stopped at a C breakpoint to risk making JVMDI calls. - private boolean javaInteractionDisabled; - - private String[] jvmLibNames; - private String[] saLibNames; - - // FIXME: make these configurable, i.e., via a dotfile; also - // consider searching within the JDK from which this Java executable - // comes to find them - private static final String defaultDbxPathPrefix = "/net/jano.eng/export/disk05/hotspot/sa"; - private static final String defaultDbxSvcAgentDSOPathPrefix = "/net/jano.eng/export/disk05/hotspot/sa"; - - private static final boolean DEBUG; - static { - DEBUG = System.getProperty("sun.jvm.hotspot.bugspot.BugSpotAgent.DEBUG") - != null; - } - - static void debugPrintln(String str) { - if (DEBUG) { - System.err.println(str); - } - } - - static void showUsage() { - System.out.println(" You can also pass these -D options to java to specify where to find dbx and the \n" + - " Serviceability Agent plugin for dbx:"); - System.out.println(" -DdbxPathName=\n" + - " Default is derived from dbxPathPrefix"); - System.out.println(" or"); - System.out.println(" -DdbxPathPrefix=\n" + - " where xxx is the path name of a dir structure that contains:\n" + - " //bin/dbx\n" + - " The default is " + defaultDbxPathPrefix); - System.out.println(" and"); - System.out.println(" -DdbxSvcAgentDSOPathName=\n" + - " Default is determined from dbxSvcAgentDSOPathPrefix"); - System.out.println(" or"); - System.out.println(" -DdbxSvcAgentDSOPathPrefix=\n" + - " where xxx is the pathname of a dir structure that contains:\n" + - " //bin/lib/libsvc_agent_dbx.so\n" + - " The default is " + defaultDbxSvcAgentDSOPathPrefix); - } - - public BugSpotAgent() { - // for non-server add shutdown hook to clean-up debugger in case - // of forced exit. For remote server, shutdown hook is added by - // DebugServer. - Runtime.getRuntime().addShutdownHook(new java.lang.Thread( - new Runnable() { - public void run() { - synchronized (BugSpotAgent.this) { - if (!isServer) { - detach(); - } - } - } - })); - } - - //-------------------------------------------------------------------------------- - // Accessors (once the system is set up) - // - - public synchronized Debugger getDebugger() { - return debugger; - } - - public synchronized CDebugger getCDebugger() { - return getDebugger().getCDebugger(); - } - - public synchronized ProcessControl getProcessControl() { - return getCDebugger().getProcessControl(); - } - - public synchronized TypeDataBase getTypeDataBase() { - return db; - } - - /** Indicates whether the target process is suspended - completely. Equivalent to getProcessControl().isSuspended(). */ - public synchronized boolean isSuspended() throws DebuggerException { - return getProcessControl().isSuspended(); - } - - /** Suspends the target process completely. Equivalent to - getProcessControl().suspend(). */ - public synchronized void suspend() throws DebuggerException { - getProcessControl().suspend(); - } - - /** Resumes the target process completely. Equivalent to - getProcessControl().suspend(). */ - public synchronized void resume() throws DebuggerException { - getProcessControl().resume(); - } - - /** Indicates whether we are attached to a Java HotSpot virtual - machine */ - public synchronized boolean isJavaMode() { - return javaMode; - } - - /** Temporarily disables interaction with the target process via - JVMDI. This is done while the target process is stopped at a C - breakpoint. Can be called even if the JVMDI agent has not been - initialized. */ - public synchronized void disableJavaInteraction() { - javaInteractionDisabled = true; - } - - /** Re-enables interaction with the target process via JVMDI. This - is done while the target process is continued past a C - braekpoint. Can be called even if the JVMDI agent has not been - initialized. */ - public synchronized void enableJavaInteraction() { - javaInteractionDisabled = false; - } - - /** Indicates whether Java interaction has been disabled */ - public synchronized boolean isJavaInteractionDisabled() { - return javaInteractionDisabled; - } - - /** Indicates whether we can talk to the Serviceability Agent's - JVMDI module to be able to set breakpoints */ - public synchronized boolean canInteractWithJava() { - return (jvmdi != null) && !javaInteractionDisabled; - } - - /** Suspends all Java threads in the target process. Can only be - called if we are attached to a HotSpot JVM and can connect to - the SA's JVMDI module. Must not be called when the target - process has been suspended with suspend(). */ - public synchronized void suspendJava() throws DebuggerException { - if (!canInteractWithJava()) { - throw new DebuggerException("Could not connect to SA's JVMDI module"); - } - if (jvmdi.isSuspended()) { - throw new DebuggerException("Target process already suspended via JVMDI"); - } - jvmdi.suspend(); - } - - /** Resumes all Java threads in the target process. Can only be - called if we are attached to a HotSpot JVM and can connect to - the SA's JVMDI module. Must not be called when the target - process has been suspended with suspend(). */ - public synchronized void resumeJava() throws DebuggerException { - if (!canInteractWithJava()) { - throw new DebuggerException("Could not connect to SA's JVMDI module"); - } - if (!jvmdi.isSuspended()) { - throw new DebuggerException("Target process already resumed via JVMDI"); - } - jvmdi.resume(); - } - - /** Indicates whether the target process has been suspended at the - Java language level via the SA's JVMDI module */ - public synchronized boolean isJavaSuspended() throws DebuggerException { - return jvmdi.isSuspended(); - } - - /** Toggle a Java breakpoint at the given location. */ - public synchronized ServiceabilityAgentJVMDIModule.BreakpointToggleResult - toggleJavaBreakpoint(String srcFileName, - String pkgName, - int lineNo) { - if (!canInteractWithJava()) { - throw new DebuggerException("Could not connect to SA's JVMDI module; can not toggle Java breakpoints"); - } - return jvmdi.toggleBreakpoint(srcFileName, pkgName, lineNo); - } - - /** Access to JVMDI module's eventPending */ - public synchronized boolean javaEventPending() throws DebuggerException { - if (!canInteractWithJava()) { - throw new DebuggerException("Could not connect to SA's JVMDI module; can not poll for Java debug events"); - } - return jvmdi.eventPending(); - } - - /** Access to JVMDI module's eventPoll */ - public synchronized Event javaEventPoll() throws DebuggerException { - if (!canInteractWithJava()) { - throw new DebuggerException("Could not connect to SA's JVMDI module; can not poll for Java debug events"); - } - return jvmdi.eventPoll(); - } - - /** Access to JVMDI module's eventContinue */ - public synchronized void javaEventContinue() throws DebuggerException { - if (!canInteractWithJava()) { - throw new DebuggerException("Could not connect to SA's JVMDI module; can not continue past Java debug events"); - } - jvmdi.eventContinue(); - } - - - // FIXME: add other accessors. For example, suspension and - // resumption should be done through this interface, as well as - // interaction with the live Java process such as breakpoint setting. - // Probably should not expose the ServiceabilityAgentJVMDIModule - // from this interface. - - //-------------------------------------------------------------------------------- - // Client-side operations - // - - /** This attaches to a process running on the local machine. */ - public synchronized void attach(int processID) - throws DebuggerException { - if (debugger != null) { - throw new DebuggerException("Already attached"); - } - pid = processID; - startupMode = PROCESS_MODE; - isServer = false; - go(); - } - - /** This opens a core file on the local machine */ - public synchronized void attach(String executableName, String coreFileName) - throws DebuggerException { - if (debugger != null) { - throw new DebuggerException("Already attached"); - } - if ((executableName == null) || (coreFileName == null)) { - throw new DebuggerException("Both the core file name and executable name must be specified"); - } - this.executableName = executableName; - this.coreFileName = coreFileName; - startupMode = CORE_FILE_MODE; - isServer = false; - go(); - } - - /** This attaches to a "debug server" on a remote machine; this - remote server has already attached to a process or opened a - core file and is waiting for RMI calls on the Debugger object to - come in. */ - public synchronized void attach(String remoteServerID) - throws DebuggerException { - if (debugger != null) { - throw new DebuggerException("Already attached to a process"); - } - if (remoteServerID == null) { - throw new DebuggerException("Debug server id must be specified"); - } - - debugServerID = remoteServerID; - startupMode = REMOTE_MODE; - isServer = false; - go(); - } - - /** This should only be called by the user on the client machine, - not the server machine */ - public synchronized boolean detach() throws DebuggerException { - if (isServer) { - throw new DebuggerException("Should not call detach() for server configuration"); - } - return detachInternal(); - } - - //-------------------------------------------------------------------------------- - // Server-side operations - // - - /** This attaches to a process running on the local machine and - starts a debug server, allowing remote machines to connect and - examine this process. uniqueID is used to uniquely identify the - debuggee */ - public synchronized void startServer(int processID, String uniqueID) - throws DebuggerException { - if (debugger != null) { - throw new DebuggerException("Already attached"); - } - pid = processID; - startupMode = PROCESS_MODE; - isServer = true; - serverID = uniqueID; - go(); - } - - /** This attaches to a process running on the local machine and - starts a debug server, allowing remote machines to connect and - examine this process. */ - public synchronized void startServer(int processID) - throws DebuggerException { - startServer(processID, null); - } - - /** This opens a core file on the local machine and starts a debug - server, allowing remote machines to connect and examine this - core file. uniqueID is used to uniquely identify the - debuggee */ - public synchronized void startServer(String executableName, String coreFileName, - String uniqueID) - throws DebuggerException { - if (debugger != null) { - throw new DebuggerException("Already attached"); - } - if ((executableName == null) || (coreFileName == null)) { - throw new DebuggerException("Both the core file name and Java executable name must be specified"); - } - this.executableName = executableName; - this.coreFileName = coreFileName; - startupMode = CORE_FILE_MODE; - isServer = true; - serverID = uniqueID; - go(); - } - - /** This opens a core file on the local machine and starts a debug - server, allowing remote machines to connect and examine this - core file.*/ - public synchronized void startServer(String executableName, String coreFileName) - throws DebuggerException { - startServer(executableName, coreFileName, null); - } - - /** This may only be called on the server side after startServer() - has been called */ - public synchronized boolean shutdownServer() throws DebuggerException { - if (!isServer) { - throw new DebuggerException("Should not call shutdownServer() for client configuration"); - } - return detachInternal(); - } - - - //-------------------------------------------------------------------------------- - // Internals only below this point - // - - private boolean detachInternal() { - if (debugger == null) { - return false; - } - if (canInteractWithJava()) { - jvmdi.detach(); - jvmdi = null; - } - boolean retval = true; - if (!isServer) { - VM.shutdown(); - } - // We must not call detach() if we are a client and are connected - // to a remote debugger - Debugger dbg = null; - DebuggerException ex = null; - if (isServer) { - try { - RMIHelper.unbind(serverID); - } - catch (DebuggerException de) { - ex = de; - } - dbg = debugger; - } else { - if (startupMode != REMOTE_MODE) { - dbg = debugger; - } - } - if (dbg != null) { - retval = dbg.detach(); - } - - debugger = null; - machDesc = null; - db = null; - if (ex != null) { - throw(ex); - } - return retval; - } - - private void go() { - setupDebugger(); - javaMode = setupVM(); - } - - private void setupDebugger() { - if (startupMode != REMOTE_MODE) { - // - // Local mode (client attaching to local process or setting up - // server, but not client attaching to server) - // - - try { - os = PlatformInfo.getOS(); - cpu = PlatformInfo.getCPU(); - } - catch (UnsupportedPlatformException e) { - throw new DebuggerException(e); - } - fileSep = System.getProperty("file.separator"); - - if (os.equals("solaris")) { - setupDebuggerSolaris(); - } else if (os.equals("win32")) { - setupDebuggerWin32(); - } else if (os.equals("linux")) { - setupDebuggerLinux(); - } else if (os.equals("bsd")) { - setupDebuggerBsd(); - } else { - // Add support for more operating systems here - throw new DebuggerException("Operating system " + os + " not yet supported"); - } - if (isServer) { - RemoteDebuggerServer remote = null; - try { - remote = new RemoteDebuggerServer(debugger); - } - catch (RemoteException rem) { - throw new DebuggerException(rem); - } - RMIHelper.rebind(serverID, remote); - } - } else { - // - // Remote mode (client attaching to server) - // - - // Create and install a security manager - - // FIXME: currently commented out because we were having - // security problems since we're "in the sun.* hierarchy" here. - // Perhaps a permissive policy file would work around this. In - // the long run, will probably have to move into com.sun.*. - - // if (System.getSecurityManager() == null) { - // System.setSecurityManager(new RMISecurityManager()); - // } - - connectRemoteDebugger(); - } - } - - private boolean setupVM() { - // We need to instantiate a HotSpotTypeDataBase on both the client - // and server machine. On the server it is only currently used to - // configure the Java primitive type sizes (which we should - // consider making constant). On the client it is used to - // configure the VM. - - try { - if (os.equals("solaris")) { - db = new HotSpotTypeDataBase(machDesc, new HotSpotSolarisVtblAccess(debugger, jvmLibNames), - debugger, jvmLibNames); - } else if (os.equals("win32")) { - db = new HotSpotTypeDataBase(machDesc, new Win32VtblAccess(debugger, jvmLibNames), - debugger, jvmLibNames); - } else if (os.equals("linux")) { - db = new HotSpotTypeDataBase(machDesc, new LinuxVtblAccess(debugger, jvmLibNames), - debugger, jvmLibNames); - } else if (os.equals("bsd")) { - db = new HotSpotTypeDataBase(machDesc, new BsdVtblAccess(debugger, jvmLibNames), - debugger, jvmLibNames); - } else { - throw new DebuggerException("OS \"" + os + "\" not yet supported (no VtblAccess implemented yet)"); - } - } - catch (NoSuchSymbolException e) { - e.printStackTrace(); - return false; - } - - if (startupMode != REMOTE_MODE) { - // Configure the debugger with the primitive type sizes just obtained from the VM - debugger.configureJavaPrimitiveTypeSizes(db.getJBooleanType().getSize(), - db.getJByteType().getSize(), - db.getJCharType().getSize(), - db.getJDoubleType().getSize(), - db.getJFloatType().getSize(), - db.getJIntType().getSize(), - db.getJLongType().getSize(), - db.getJShortType().getSize()); - } - - if (!isServer) { - // Do not initialize the VM on the server (unnecessary, since it's - // instantiated on the client) - VM.initialize(db, debugger); - } - - try { - jvmdi = new ServiceabilityAgentJVMDIModule(debugger, saLibNames); - if (jvmdi.canAttach()) { - jvmdi.attach(); - jvmdi.setCommandTimeout(6000); - debugPrintln("Attached to Serviceability Agent's JVMDI module."); - // Jog VM to suspended point with JVMDI module - resume(); - suspendJava(); - suspend(); - debugPrintln("Suspended all Java threads."); - } else { - debugPrintln("Could not locate SA's JVMDI module; skipping attachment"); - jvmdi = null; - } - } catch (Exception e) { - e.printStackTrace(); - jvmdi = null; - } - - return true; - } - - //-------------------------------------------------------------------------------- - // OS-specific debugger setup/connect routines - // - - // - // Solaris - // - - private void setupDebuggerSolaris() { - setupJVMLibNamesSolaris(); - ProcDebuggerLocal dbg = new ProcDebuggerLocal(null, true); - debugger = dbg; - attachDebugger(); - - // Set up CPU-dependent stuff - if (cpu.equals("x86")) { - machDesc = new MachineDescriptionIntelX86(); - } else if (cpu.equals("sparc")) { - int addressSize = dbg.getRemoteProcessAddressSize(); - if (addressSize == -1) { - throw new DebuggerException("Error occurred while trying to determine the remote process's address size"); - } - - if (addressSize == 32) { - machDesc = new MachineDescriptionSPARC32Bit(); - } else if (addressSize == 64) { - machDesc = new MachineDescriptionSPARC64Bit(); - } else { - throw new DebuggerException("Address size " + addressSize + " is not supported on SPARC"); - } - } else if (cpu.equals("amd64")) { - machDesc = new MachineDescriptionAMD64(); - } else { - throw new DebuggerException("Solaris only supported on sparc/sparcv9/x86/amd64"); - } - - dbg.setMachineDescription(machDesc); - } - - private void connectRemoteDebugger() throws DebuggerException { - RemoteDebugger remote = - (RemoteDebugger) RMIHelper.lookup(debugServerID); - debugger = new RemoteDebuggerClient(remote); - machDesc = ((RemoteDebuggerClient) debugger).getMachineDescription(); - os = debugger.getOS(); - if (os.equals("solaris")) { - setupJVMLibNamesSolaris(); - } else if (os.equals("win32")) { - setupJVMLibNamesWin32(); - } else if (os.equals("linux")) { - setupJVMLibNamesLinux(); - } else if (os.equals("bsd")) { - setupJVMLibNamesBsd(); - } else { - throw new RuntimeException("Unknown OS type"); - } - - cpu = debugger.getCPU(); - } - - private void setupJVMLibNamesSolaris() { - jvmLibNames = new String[] { "libjvm.so", "libjvm_g.so", "gamma_g" }; - saLibNames = new String[] { "libsa.so", "libsa_g.so" }; - } - - // - // Win32 - // - - private void setupDebuggerWin32() { - setupJVMLibNamesWin32(); - - if (cpu.equals("x86")) { - machDesc = new MachineDescriptionIntelX86(); - } else if (cpu.equals("amd64")) { - machDesc = new MachineDescriptionAMD64(); - } else if (cpu.equals("ia64")) { - machDesc = new MachineDescriptionIA64(); - } else { - throw new DebuggerException("Win32 supported under x86, amd64 and ia64 only"); - } - - // Note we do not use a cache for the local debugger in server - // mode; it will be taken care of on the client side (once remote - // debugging is implemented). - - debugger = new WindbgDebuggerLocal(machDesc, !isServer); - - attachDebugger(); - } - - private void setupJVMLibNamesWin32() { - jvmLibNames = new String[] { "jvm.dll", "jvm_g.dll" }; - saLibNames = new String[] { "sa.dll", "sa_g.dll" }; - } - - // - // Linux - // - - private void setupDebuggerLinux() { - setupJVMLibNamesLinux(); - - if (cpu.equals("x86")) { - machDesc = new MachineDescriptionIntelX86(); - } else if (cpu.equals("ia64")) { - machDesc = new MachineDescriptionIA64(); - } else if (cpu.equals("amd64")) { - machDesc = new MachineDescriptionAMD64(); - } else if (cpu.equals("sparc")) { - if (LinuxDebuggerLocal.getAddressSize()==8) { - machDesc = new MachineDescriptionSPARC64Bit(); - } else { - machDesc = new MachineDescriptionSPARC32Bit(); - } - } else { - try { - machDesc = (MachineDescription) - Class.forName("sun.jvm.hotspot.debugger.MachineDescription" + - cpu.toUpperCase()).newInstance(); - } catch (Exception e) { - throw new DebuggerException("unsupported machine type"); - } - } - - - // Note we do not use a cache for the local debugger in server - // mode; it will be taken care of on the client side (once remote - // debugging is implemented). - - debugger = new LinuxDebuggerLocal(machDesc, !isServer); - attachDebugger(); - } - - private void setupJVMLibNamesLinux() { - // same as solaris - setupJVMLibNamesSolaris(); - } - - // - // BSD - // - - private void setupDebuggerBsd() { - setupJVMLibNamesBsd(); - - if (cpu.equals("x86")) { - machDesc = new MachineDescriptionIntelX86(); - } else if (cpu.equals("amd64") || (cpu.equals("x86_64"))) { - machDesc = new MachineDescriptionAMD64(); - } else { - throw new DebuggerException("Bsd only supported on x86/x86_64. Current arch: " + cpu); - } - - // Note we do not use a cache for the local debugger in server - // mode; it will be taken care of on the client side (once remote - // debugging is implemented). - - debugger = new BsdDebuggerLocal(machDesc, !isServer); - attachDebugger(); - } - - private void setupJVMLibNamesBsd() { - // same as solaris - setupJVMLibNamesSolaris(); - } - - /** Convenience routine which should be called by per-platform - debugger setup. Should not be called when startupMode is - REMOTE_MODE. */ - private void attachDebugger() { - if (startupMode == PROCESS_MODE) { - debugger.attach(pid); - } else if (startupMode == CORE_FILE_MODE) { - debugger.attach(executableName, coreFileName); - } else { - throw new DebuggerException("Should not call attach() for startupMode == " + startupMode); - } - } -} diff -r a413bcd552a4 -r 5fc51c1ecdeb agent/src/share/classes/sun/jvm/hotspot/bugspot/JavaLineNumberInfo.java --- a/agent/src/share/classes/sun/jvm/hotspot/bugspot/JavaLineNumberInfo.java Tue Mar 05 21:58:51 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,55 +0,0 @@ -/* - * Copyright (c) 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. - * - * 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 sun.jvm.hotspot.bugspot; - -import sun.jvm.hotspot.oops.*; - -/** Wrapper class which describes line number information for Java - class files. The line number table is converted into this - representation on demand. These objects are then sorted by line - number for fast lookup when setting breakpoints in a particular - source file. */ - -public class JavaLineNumberInfo { - private InstanceKlass klass; - private Method method; - private int startBCI; - private int lineNumber; - - public JavaLineNumberInfo(InstanceKlass klass, - Method method, - int startBCI, - int lineNumber) { - this.klass = klass; - this.method = method; - this.startBCI = startBCI; - this.lineNumber = lineNumber; - } - - public InstanceKlass getKlass() { return klass; } - public Method getMethod() { return method; } - public int getStartBCI() { return startBCI; } - public int getLineNumber() { return lineNumber; } -} diff -r a413bcd552a4 -r 5fc51c1ecdeb agent/src/share/classes/sun/jvm/hotspot/bugspot/Main.java --- a/agent/src/share/classes/sun/jvm/hotspot/bugspot/Main.java Tue Mar 05 21:58:51 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2001, 2008, 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 sun.jvm.hotspot.bugspot; - -import java.awt.*; -import java.awt.event.*; -import javax.swing.*; - -import sun.jvm.hotspot.ui.*; - -/** The main class for the BugSpot debugger. */ - -public class Main { - public static void main(String[] args) { - JFrame frame = new JFrame("BugSpot"); - frame.setSize(800, 600); - BugSpot db = new BugSpot(); - db.setMDIMode(true); - db.build(); - frame.setJMenuBar(db.getMenuBar()); - frame.getContentPane().add(db); - frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); - - GraphicsUtilities.reshapeToAspectRatio(frame, - 4.0f/3.0f, 0.85f, Toolkit.getDefaultToolkit().getScreenSize()); - GraphicsUtilities.centerInContainer(frame, - Toolkit.getDefaultToolkit().getScreenSize()); - frame.setVisible(true); - } -} diff -r a413bcd552a4 -r 5fc51c1ecdeb agent/src/share/classes/sun/jvm/hotspot/bugspot/PCFinder.java --- a/agent/src/share/classes/sun/jvm/hotspot/bugspot/PCFinder.java Tue Mar 05 21:58:51 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,96 +0,0 @@ -/* - * Copyright (c) 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. - * - * 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 sun.jvm.hotspot.bugspot; - -import sun.jvm.hotspot.debugger.*; -import sun.jvm.hotspot.debugger.cdbg.*; - -/** Helper class for locating a program counter. Indicates the - confidence of the find. */ - -public class PCFinder { - public static final int LOW_CONFIDENCE = 1; - public static final int HIGH_CONFIDENCE = 2; - - public static class Info { - private String name; - private long offset; - private int confidence; - - public Info(String name, long offset, int confidence) { - this.name = name; - this.offset = offset; - this.confidence = confidence; - } - - /** May be null */ - public String getName() { return name; } - - /** If this is -1, a symbol could not be found, and the offset - should not be shown */ - public long getOffset() { return offset; } - - /** PCFinder.LOW_CONFIDENCE or PCFinder.HIGH_CONFIDENCE */ - public int getConfidence() { return confidence; } - } - - /** Passed loadobject may be null in which case the returned Info - object has low confidence */ - public static Info findPC(Address pc, LoadObject lo, CDebugger dbg) { - if (lo == null) { - return new Info(null, -1, LOW_CONFIDENCE); - } - - // First try debug info - BlockSym sym = lo.debugInfoForPC(pc); - while (sym != null) { - if (sym.isFunction()) { - // Highest confidence - return new Info(sym.toString(), pc.minus(sym.getAddress()), HIGH_CONFIDENCE); - } - } - - // Now try looking up symbol in loadobject - - // FIXME: must add support for mapfiles on Win32 and try looking - // up there first if possible. Should we hide that behind - // LoadObject.closestSymbolToPC and have the ClosestSymbol return - // confidence? I think so. On Solaris there is no notion of a - // mapfile, and the confidence for closestSymbolToPC will be high - // instead of low. - - int confidence = HIGH_CONFIDENCE; - - ClosestSymbol cs = lo.closestSymbolToPC(pc); - if (cs != null) { - // FIXME: currently low confidence (only on Win32) - return new Info(cs.getName() + "()", cs.getOffset(), LOW_CONFIDENCE); - } - - // Unknown location - return new Info(dbg.getNameOfFile(lo.getName()).toUpperCase() + - "! " + pc + "()", -1, HIGH_CONFIDENCE); - } -} diff -r a413bcd552a4 -r 5fc51c1ecdeb agent/src/share/classes/sun/jvm/hotspot/bugspot/PackageScanner.java --- a/agent/src/share/classes/sun/jvm/hotspot/bugspot/PackageScanner.java Tue Mar 05 21:58:51 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,89 +0,0 @@ -/* - * Copyright (c) 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. - * - * 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 sun.jvm.hotspot.bugspot; - -import java.io.*; - -/** Scans a .java file for the package that it is in. */ - -public class PackageScanner { - - public PackageScanner() { - } - - public String scan(String filename) { - return scan(new File(filename)); - } - - /** Returns the String comprising the package name of the classes in - this .java file. Returns the (non-null) empty string if any - error occurs or if the classes are in the unnamed package. */ - public String scan(File file) { - BufferedReader buf = null; - String res = ""; - try { - buf = new BufferedReader(new FileReader(file)); - StreamTokenizer tok = new StreamTokenizer(buf); - tok.slashStarComments(true); - tok.slashSlashComments(true); - if (tok.nextToken() != StreamTokenizer.TT_WORD) { - return res; - } - if (!tok.sval.equals("package")) { - return res; - } - if (tok.nextToken() != StreamTokenizer.TT_WORD) { - return res; - } - res = tok.sval; - return res; - } catch (FileNotFoundException e) { - return res; - } catch (IOException e) { - return res; - } finally { - try { - if (buf != null) { - buf.close(); - } - } catch (IOException e) { - } - } - } - - public static void main(String[] args) { - if (args.length != 1) { - usage(); - } - - System.out.println(new PackageScanner().scan(args[0])); - } - - private static void usage() { - System.err.println("Usage: java PackageScanner <.java file name>"); - System.err.println("Prints package the .java file is in to stdout."); - System.exit(1); - } -} diff -r a413bcd552a4 -r 5fc51c1ecdeb agent/src/share/classes/sun/jvm/hotspot/bugspot/RegisterPanel.java --- a/agent/src/share/classes/sun/jvm/hotspot/bugspot/RegisterPanel.java Tue Mar 05 21:58:51 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,173 +0,0 @@ -/* - * Copyright (c) 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. - * - * 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 sun.jvm.hotspot.bugspot; - -import java.awt.*; -import java.util.*; -import javax.swing.*; -import javax.swing.table.*; - -import sun.jvm.hotspot.debugger.*; - -/** Displays registers in a window. FIXME: this will need more work to - understand and handle register windows. */ - -public class RegisterPanel extends JPanel { - private java.util.List/**/ registers; - private AbstractTableModel dataModel; - private boolean valid; - private boolean editable; - private String nullAddressString; - private ThreadProxy curThread; - private JTable table; - - static class RegisterInfo { - private String name; - private Address value; - - RegisterInfo(String name, Address value) { - this.name = name; - this.value = value; - } - - String getName() { return name; } - Address getValue() { return value; } - } - - public RegisterPanel() { - super(); - - registers = new ArrayList(); - - dataModel = new AbstractTableModel() { - public int getColumnCount() { return 2; } - public int getRowCount() { return registers.size(); } - public String getColumnName(int col) { - switch (col) { - case 0: - return "Register Name"; - case 1: - return "Register Value"; - default: - throw new RuntimeException("Index " + col + " out of bounds"); - } - } - public Object getValueAt(int row, int col) { - RegisterInfo info = (RegisterInfo) registers.get(row); - - switch (col) { - case 0: - return info.getName(); - case 1: - if (valid) { - Address val = info.getValue(); - if (val != null) { - return val; - } else { - return nullAddressString; - } - } else { - return "-"; - } - default: - throw new RuntimeException("Index (" + col + ", " + row + ") out of bounds"); - } - } - public boolean isCellEditable(int row, int col) { - if (col == 0) return false; - if (!valid) return false; - if (curThread == null) return false; - if (!curThread.canSetContext()) return false; - - // FIXME: add listener to watch for register changes - // return true; - return false; - } - }; - - // Build user interface - setLayout(new BorderLayout()); - table = new JTable(dataModel); - table.setCellSelectionEnabled(true); - table.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION); - table.setDragEnabled(true); - JTableHeader header = table.getTableHeader(); - header.setReorderingAllowed(false); - JScrollPane scrollPane = new JScrollPane(table); - add(scrollPane, BorderLayout.CENTER); - } - - - /** Updates the register panel with the register set from the - specified thread. Call this when the process has been suspended - and the current thread has been set. FIXME: this interface will - need to change to support register windows. */ - public void update(ThreadProxy curThread) { - this.curThread = curThread; - ThreadContext context = curThread.getContext(); - editable = curThread.canSetContext(); - registers.clear(); - for (int i = 0; i < context.getNumRegisters(); i++) { - String name = context.getRegisterName(i); - Address addr = context.getRegisterAsAddress(i); - if ((nullAddressString == null) && (addr != null)) { - String addrStr = addr.toString(); - StringBuffer buf = new StringBuffer(); - buf.append("0x"); - int len = addrStr.length() - 2; - for (int j = 0; j < len; j++) { - buf.append("0"); - } - nullAddressString = buf.toString(); - } - registers.add(new RegisterInfo(name, addr)); - } - valid = true; - SwingUtilities.invokeLater(new Runnable() { - public void run() { - dataModel.fireTableDataChanged(); - } - }); - } - - /** Clears the registers' values. Call this when the processs has - been resumed. */ - public void clear() { - valid = false; - nullAddressString = null; - SwingUtilities.invokeLater(new Runnable() { - public void run() { - dataModel.fireTableDataChanged(); - } - }); - } - - public void setFont(Font font) { - super.setFont(font); - if (table != null) { - table.setFont(font); - } - } -} diff -r a413bcd552a4 -r 5fc51c1ecdeb agent/src/share/classes/sun/jvm/hotspot/bugspot/StackTraceEntry.java --- a/agent/src/share/classes/sun/jvm/hotspot/bugspot/StackTraceEntry.java Tue Mar 05 21:58:51 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,87 +0,0 @@ -/* - * Copyright (c) 2001, 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. - * - * 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 sun.jvm.hotspot.bugspot; - -import sun.jvm.hotspot.debugger.cdbg.*; -import sun.jvm.hotspot.oops.*; -import sun.jvm.hotspot.runtime.*; - -/** This class describes a frame in a stack trace. It abstracts over - C/C++ and Java frames. */ - -public class StackTraceEntry { - private CFrame cFrame; - private CDebugger dbg; - private JavaVFrame javaFrame; - private String value; // What is displayed in a stack trace - // For merging C and Java stack traces. - // For more precise stack traces, should probably have a way to - // convert a CFrame to a sun.jvm.hotspot.runtime.Frame. For now, - // doing similar algorithm to jdbx (which does not have intimate - // knowledge of the VM). - private boolean isUnknownCFrame; - - public StackTraceEntry(CFrame cFrame, CDebugger dbg) { - this.cFrame = cFrame; - this.dbg = dbg; - computeValue(); - } - - public StackTraceEntry(JavaVFrame javaFrame) { - this.javaFrame = javaFrame; - computeValue(); - } - - public boolean isCFrame() { return (cFrame != null); } - public boolean isJavaFrame() { return (javaFrame != null); } - public CFrame getCFrame() { return cFrame; } - public JavaVFrame getJavaFrame() { return javaFrame; } - public boolean isUnknownCFrame() { return isUnknownCFrame; } - public String toString() { - return value; - } - - private void computeValue() { - isUnknownCFrame = true; - value = ""; - if (cFrame != null) { - PCFinder.Info info = PCFinder.findPC(cFrame.pc(), cFrame.loadObjectForPC(), dbg); - if (info.getName() != null) { - value = "(C) " + info.getName(); - isUnknownCFrame = false; - if (info.getConfidence() == PCFinder.LOW_CONFIDENCE) { - value = value + " (?)"; - } - if (info.getOffset() >= 0) { - value = value + " + 0x" + Long.toHexString(info.getOffset()); - } - } - } else if (javaFrame != null) { - isUnknownCFrame = false; - Method m = javaFrame.getMethod(); - value = "(J) " + m.externalNameAndSignature(); - } - } -} diff -r a413bcd552a4 -r 5fc51c1ecdeb agent/src/share/classes/sun/jvm/hotspot/bugspot/StackTracePanel.java --- a/agent/src/share/classes/sun/jvm/hotspot/bugspot/StackTracePanel.java Tue Mar 05 21:58:51 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,115 +0,0 @@ -/* - * Copyright (c) 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. - * - * 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 sun.jvm.hotspot.bugspot; - -import java.awt.*; -import java.awt.event.*; -import java.util.*; -import javax.swing.*; -import sun.jvm.hotspot.debugger.cdbg.*; -import sun.jvm.hotspot.runtime.*; -import sun.jvm.hotspot.ui.*; - -/** This panel contains a ListBox with all of the stack frames in a - given thread. When a given entry is selected, an event is - fired. */ - -public class StackTracePanel extends JPanel { - public interface Listener { - public void frameChanged(CFrame fr, JavaVFrame jfr); - } - - class Model extends AbstractListModel implements ComboBoxModel { - private Object selectedItem; - public Object getElementAt(int index) { - if (trace == null) return null; - return trace.get(index); - } - public int getSize() { - if (trace == null) return 0; - return trace.size(); - } - public Object getSelectedItem() { - return selectedItem; - } - public void setSelectedItem(Object item) { - selectedItem = item; - } - public void dataChanged() { - fireContentsChanged(this, 0, trace.size()); - } - } - - private java.util.List trace; - private Model model; - private JComboBox list; - private java.util.List listeners; - - public StackTracePanel() { - super(); - - model = new Model(); - - // Build user interface - setLayout(new BorderLayout()); - setBorder(GraphicsUtilities.newBorder(5)); - list = new JComboBox(model); - list.setPrototypeDisplayValue("ZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"); - add(list, BorderLayout.CENTER); - - // Add selection listener - list.addItemListener(new ItemListener() { - public void itemStateChanged(ItemEvent e) { - if (e.getStateChange() == ItemEvent.SELECTED) { - fireFrameChanged(); - } - } - }); - } - - /** Takes a List of StackTraceEntry objects */ - public void setTrace(java.util.List trace) { - this.trace = trace; - model.dataChanged(); - list.setSelectedIndex(0); - fireFrameChanged(); - } - - public void addListener(Listener listener) { - if (listeners == null) { - listeners = new ArrayList(); - } - listeners.add(listener); - } - - protected void fireFrameChanged() { - if (listeners != null) { - StackTraceEntry entry = (StackTraceEntry) trace.get(list.getSelectedIndex()); - for (Iterator iter = listeners.iterator(); iter.hasNext(); ) { - ((Listener) iter.next()).frameChanged(entry.getCFrame(), entry.getJavaFrame()); - } - } - } -} diff -r a413bcd552a4 -r 5fc51c1ecdeb agent/src/share/classes/sun/jvm/hotspot/bugspot/ThreadListPanel.java --- a/agent/src/share/classes/sun/jvm/hotspot/bugspot/ThreadListPanel.java Tue Mar 05 21:58:51 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,237 +0,0 @@ -/* - * Copyright (c) 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. - * - * 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 sun.jvm.hotspot.bugspot; - -import java.awt.*; -import java.awt.event.*; -import java.util.*; -import javax.swing.*; -import javax.swing.table.*; - -import sun.jvm.hotspot.debugger.*; -import sun.jvm.hotspot.debugger.cdbg.*; -import sun.jvm.hotspot.runtime.*; -import sun.jvm.hotspot.ui.*; - -// NOTE: this class was not placed in sun.jvm.hotspot.ui to prevent -// mixing components designed for C and C++ debugging with the ones -// that work with the core serviceability agent functionality (which -// does not require that the CDebugger interface be implemented). - -/** The ThreadListPanel is used for C and C++ debugging and can - visualize all threads in the target process. The caller passes in - a CDebugger attached to the target process and can request that - JavaThreads' associations with these underlying threads be - displayed; this option is only valid when attached to a HotSpot - JVM and when the {@link sun.jvm.hotspot.runtime.VM} has been - initialized. */ - -public class ThreadListPanel extends JPanel { - /** Listener which can be added to receive "Set Focus" events */ - public static interface Listener { - /** ThreadProxy will always be provided; JavaThread will only be - present if displayJavaThreads was specified in the constructor - for the panel and the thread was a JavaThread. */ - public void setFocus(ThreadProxy thread, JavaThread jthread); - } - - static class ThreadInfo { - private ThreadProxy thread; - // Distinguish between PC == null and no top frame - private boolean gotPC; - private Address pc; - private String location; - private JavaThread javaThread; - private String javaThreadName; - - public ThreadInfo(ThreadProxy thread, CDebugger dbg, JavaThread jthread) { - this.thread = thread; - this.location = ""; - CFrame fr = dbg.topFrameForThread(thread); - if (fr != null) { - gotPC = true; - pc = fr.pc(); - PCFinder.Info info = PCFinder.findPC(pc, fr.loadObjectForPC(), dbg); - if (info.getName() != null) { - location = info.getName(); - if (info.getConfidence() == PCFinder.LOW_CONFIDENCE) { - location = location + " (?)"; - } - if (info.getOffset() < 0) { - location = location + " + 0x" + Long.toHexString(info.getOffset()); - } - } - } - if (jthread != null) { - javaThread = jthread; - javaThreadName = jthread.getThreadName(); - } - } - - public ThreadProxy getThread() { return thread; } - public boolean hasPC() { return gotPC; } - public Address getPC() { return pc; } - public String getLocation() { return location; } - public boolean isJavaThread() { return (javaThread != null); } - public JavaThread getJavaThread() { return javaThread; } - public String getJavaThreadName() { return javaThreadName; } - } - - // List - private java.util.List threadList; - private JTable table; - private AbstractTableModel dataModel; - // List - private java.util.List listeners; - - /** Takes a CDebugger from which the thread list is queried. - displayJavaThreads must only be set to true if the debugger is - attached to a HotSpot JVM and if the VM has already been - initialized. */ - public ThreadListPanel(CDebugger dbg, final boolean displayJavaThreads) { - super(); - - Map threadToJavaThreadMap = null; - if (displayJavaThreads) { - // Collect Java threads from virtual machine and insert them in - // table for later querying - threadToJavaThreadMap = new HashMap(); - Threads threads = VM.getVM().getThreads(); - for (JavaThread thr = threads.first(); thr != null; thr = thr.next()) { - threadToJavaThreadMap.put(thr.getThreadProxy(), thr); - } - } - - java.util.List/**/ threads = dbg.getThreadList(); - threadList = new ArrayList(threads.size()); - for (Iterator iter = threads.iterator(); iter.hasNext(); ) { - ThreadProxy thr = (ThreadProxy) iter.next(); - JavaThread jthr = null; - if (displayJavaThreads) { - jthr = (JavaThread) threadToJavaThreadMap.get(thr); - } - threadList.add(new ThreadInfo(thr, dbg, jthr)); - } - - // Thread ID, current PC, current symbol, Java Thread, [Java thread name] - dataModel = new AbstractTableModel() { - public int getColumnCount() { return (displayJavaThreads ? 5 : 3); } - public int getRowCount() { return threadList.size(); } - public String getColumnName(int col) { - switch (col) { - case 0: - return "Thread ID"; - case 1: - return "PC"; - case 2: - return "Location"; - case 3: - return "Java?"; - case 4: - return "Java Thread Name"; - default: - throw new RuntimeException("Index " + col + " out of bounds"); - } - } - public Object getValueAt(int row, int col) { - ThreadInfo info = (ThreadInfo) threadList.get(row); - - switch (col) { - case 0: - return info.getThread(); - case 1: - { - if (info.hasPC()) { - return info.getPC(); - } - return ""; - } - case 2: - return info.getLocation(); - case 3: - if (info.isJavaThread()) { - return "Yes"; - } else { - return ""; - } - case 4: - if (info.isJavaThread()) { - return info.getJavaThreadName(); - } else { - return ""; - } - default: - throw new RuntimeException("Index (" + col + ", " + row + ") out of bounds"); - } - } - }; - - // Build user interface - setLayout(new BorderLayout()); - table = new JTable(dataModel); - table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); - JTableHeader header = table.getTableHeader(); - header.setReorderingAllowed(false); - table.setRowSelectionAllowed(true); - table.setColumnSelectionAllowed(false); - JScrollPane scrollPane = new JScrollPane(table); - add(scrollPane, BorderLayout.CENTER); - if (threadList.size() > 0) { - table.setRowSelectionInterval(0, 0); - } - - JButton button = new JButton("Set Focus"); - button.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - int i = table.getSelectedRow(); - if (i < 0) { - return; - } - ThreadInfo info = (ThreadInfo) threadList.get(i); - for (Iterator iter = listeners.iterator(); iter.hasNext(); ) { - ((Listener) iter.next()).setFocus(info.getThread(), info.getJavaThread()); - } - } - }); - JPanel focusPanel = new JPanel(); - focusPanel.setBorder(BorderFactory.createEmptyBorder(0, 5, 0, 0)); - focusPanel.setLayout(new BoxLayout(focusPanel, BoxLayout.Y_AXIS)); - focusPanel.add(Box.createGlue()); - focusPanel.add(button); - focusPanel.add(Box.createGlue()); - add(focusPanel, BorderLayout.EAST); - - // FIXME: make listener model for the debugger so if the user - // specifies a mapfile for or path to a given DSO later we can - // update our state - } - - public void addListener(Listener l) { - if (listeners == null) { - listeners = new ArrayList(); - } - listeners.add(l); - } -} diff -r a413bcd552a4 -r 5fc51c1ecdeb agent/src/share/classes/sun/jvm/hotspot/bugspot/VariablePanel.java --- a/agent/src/share/classes/sun/jvm/hotspot/bugspot/VariablePanel.java Tue Mar 05 21:58:51 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,252 +0,0 @@ -/* - * Copyright (c) 2001, 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. - * - * 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 sun.jvm.hotspot.bugspot; - -import java.awt.*; -import javax.swing.*; -import java.util.*; -import sun.jvm.hotspot.debugger.*; -import sun.jvm.hotspot.debugger.cdbg.*; -import sun.jvm.hotspot.bugspot.tree.*; -import sun.jvm.hotspot.oops.*; -import sun.jvm.hotspot.runtime.*; -import sun.jvm.hotspot.ui.tree.*; -import sun.jvm.hotspot.ui.treetable.*; - -/** Manages display of a set of local variables in a frame, or the - contents of the "this" pointer */ - -public class VariablePanel extends JPanel { - private JTreeTable treeTable; - private SimpleTreeTableModel model; - private SimpleTreeGroupNode root; - - public VariablePanel() { - super(); - - model = new SimpleTreeTableModel(); - model.setValuesEditable(false); - root = new SimpleTreeGroupNode(); - model.setRoot(root); - treeTable = new JTreeTable(model); - treeTable.setRootVisible(false); - treeTable.setShowsRootHandles(true); - treeTable.setShowsIcons(false); - treeTable.setTreeEditable(false); - treeTable.getTableHeader().setReorderingAllowed(false); - treeTable.setCellSelectionEnabled(true); - treeTable.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION); - treeTable.setDragEnabled(true); - JScrollPane sp = new JScrollPane(treeTable); - sp.getViewport().setBackground(Color.white); - - setLayout(new BorderLayout()); - add(sp, BorderLayout.CENTER); - } - - /** Clear the contents of this VariablePanel */ - public void clear() { - root.removeAllChildren(); - model.fireTreeStructureChanged(); - } - - /** Update the contents of this VariablePanel from the given CFrame */ - public void update(CFrame fr) { - // Collect locals - CCollector coll = new CCollector(); - fr.iterateLocals(coll); - update(coll); - } - - /** Update the contents of this VariablePanel from the given JavaVFrame */ - public void update(JavaVFrame jfr) { - Method m = jfr.getMethod(); - if (!m.hasLocalVariableTable()) { - return; - } - int bci = jfr.getBCI(); - // Get local variable table - LocalVariableTableElement[] locals = m.getLocalVariableTable(); - // Get locals as StackValueCollection - StackValueCollection coll = jfr.getLocals(); - root.removeAllChildren(); - // See which locals are live - for (int i = 0; i < locals.length; i++) { - LocalVariableTableElement local = locals[i]; - if (local.getStartBCI() <= bci && bci < local.getStartBCI() + local.getLength()) { - // Valid; add it - SimpleTreeNode node = null; - Symbol name = null; - try { - name = m.getConstants().getSymbolAt(local.getNameCPIndex()); - if (name == null) { - System.err.println("Null name at slot " + - local.getNameCPIndex() + - " for local variable at slot " + - local.getSlot()); - continue; - } - } catch (Exception e) { - System.err.println("Unable to fetch name at slot " + - local.getNameCPIndex() + - " for local variable at slot " + - local.getSlot()); - e.printStackTrace(); - continue; - } - sun.jvm.hotspot.oops.NamedFieldIdentifier f = - new sun.jvm.hotspot.oops.NamedFieldIdentifier(name.asString()); - Symbol descriptor = null; - try { - descriptor = m.getConstants().getSymbolAt(local.getDescriptorCPIndex()); - } catch (Exception e) { - System.err.println("Unable to fetch descriptor at slot " + - local.getDescriptorCPIndex() + - " for local variable " + f.getName() + - " at slot " + local.getSlot()); - e.printStackTrace(); - continue; - } - - if (descriptor != null) { - switch (descriptor.getByteAt(0)) { - case 'F': { - node = new sun.jvm.hotspot.ui.tree.FloatTreeNodeAdapter(coll.floatAt(local.getSlot()), f, true); - break; - } - case 'D': { - node = new sun.jvm.hotspot.ui.tree.DoubleTreeNodeAdapter(coll.doubleAt(local.getSlot()), f, true); - break; - } - case 'C': { - node = new sun.jvm.hotspot.ui.tree.CharTreeNodeAdapter((char) coll.intAt(local.getSlot()), f, true); - break; - } - case 'B': - case 'S': - case 'I': { - node = new sun.jvm.hotspot.ui.tree.LongTreeNodeAdapter(coll.intAt(local.getSlot()), f, true); - break; - } - case 'Z': { - node = new sun.jvm.hotspot.ui.tree.BooleanTreeNodeAdapter( - ((coll.intAt(local.getSlot()) != 0) ? true : false), f, true - ); - break; - } - case 'J': { - node = new sun.jvm.hotspot.ui.tree.LongTreeNodeAdapter(coll.longAt(local.getSlot()), f, true); - break; - } - default: { - try { - node = new sun.jvm.hotspot.ui.tree.OopTreeNodeAdapter( - VM.getVM().getObjectHeap().newOop(coll.oopHandleAt(local.getSlot())), f, true - ); - } catch (AddressException e) { - node = new sun.jvm.hotspot.ui.tree.FieldTreeNodeAdapter(f, true) { - public int getChildCount() { return 0; } - public SimpleTreeNode getChild(int i) { return null; } - public boolean isLeaf() { return false; } - public int getIndexOfChild(SimpleTreeNode child) { return 0; } - public String getValue() { - return ""; - } - }; - } - break; - } - } - if (node != null) { - root.addChild(node); - } - } - } - } - - model.fireTreeStructureChanged(); - } - - /** Update the contents of this VariablePanel from the given "this" - pointer of the given type */ - public void update(Address thisAddr, Type type) { - // Collect fields - CCollector coll = new CCollector(); - type.iterateObject(thisAddr, coll); - update(coll); - } - - private void update(CCollector coll) { - root.removeAllChildren(); - for (int i = 0; i < coll.getNumChildren(); i++) { - root.addChild(coll.getChild(i)); - } - model.fireTreeStructureChanged(); - } - - static class CCollector extends DefaultObjectVisitor { - private java.util.List children; - - public CCollector() { - children = new ArrayList(); - } - - public int getNumChildren() { - return children.size(); - } - - public SimpleTreeNode getChild(int i) { - return (SimpleTreeNode) children.get(i); - } - - public void doBit(sun.jvm.hotspot.debugger.cdbg.FieldIdentifier f, long val) { - children.add(new sun.jvm.hotspot.bugspot.tree.LongTreeNodeAdapter(val, f, true)); - } - public void doInt(sun.jvm.hotspot.debugger.cdbg.FieldIdentifier f, long val) { - children.add(new sun.jvm.hotspot.bugspot.tree.LongTreeNodeAdapter(val, f, true)); - } - public void doEnum(sun.jvm.hotspot.debugger.cdbg.FieldIdentifier f, long val, String enumName) { - children.add(new sun.jvm.hotspot.bugspot.tree.EnumTreeNodeAdapter(enumName, val, f, true)); - } - public void doFloat(sun.jvm.hotspot.debugger.cdbg.FieldIdentifier f, float val) { - children.add(new sun.jvm.hotspot.bugspot.tree.FloatTreeNodeAdapter(val, f, true)); - } - public void doDouble(sun.jvm.hotspot.debugger.cdbg.FieldIdentifier f, double val) { - children.add(new sun.jvm.hotspot.bugspot.tree.DoubleTreeNodeAdapter(val, f, true)); - } - public void doPointer(sun.jvm.hotspot.debugger.cdbg.FieldIdentifier f, Address val) { - children.add(new sun.jvm.hotspot.bugspot.tree.AddressTreeNodeAdapter(val, f, true)); - } - public void doArray(sun.jvm.hotspot.debugger.cdbg.FieldIdentifier f, Address val) { - children.add(new sun.jvm.hotspot.bugspot.tree.AddressTreeNodeAdapter(val, f, true)); - } - public void doRef(sun.jvm.hotspot.debugger.cdbg.FieldIdentifier f, Address val) { - children.add(new sun.jvm.hotspot.bugspot.tree.AddressTreeNodeAdapter(val, f, true)); - } - public void doCompound(sun.jvm.hotspot.debugger.cdbg.FieldIdentifier f, Address val) { - children.add(new sun.jvm.hotspot.bugspot.tree.ObjectTreeNodeAdapter(val, f, true)); - } - } -} diff -r a413bcd552a4 -r 5fc51c1ecdeb agent/src/share/classes/sun/jvm/hotspot/bugspot/tree/AddressTreeNodeAdapter.java --- a/agent/src/share/classes/sun/jvm/hotspot/bugspot/tree/AddressTreeNodeAdapter.java Tue Mar 05 21:58:51 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,67 +0,0 @@ -/* - * Copyright (c) 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. - * - * 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 sun.jvm.hotspot.bugspot.tree; - -import sun.jvm.hotspot.debugger.*; -import sun.jvm.hotspot.debugger.cdbg.*; -import sun.jvm.hotspot.ui.tree.SimpleTreeNode; - -/** Encapsulates a float value in a tree handled by SimpleTreeModel */ - -public class AddressTreeNodeAdapter extends FieldTreeNodeAdapter { - private Address val; - - public AddressTreeNodeAdapter(Address val, FieldIdentifier id) { - this(val, id, false); - } - - public AddressTreeNodeAdapter(Address val, FieldIdentifier id, boolean treeTableMode) { - super(id, treeTableMode); - this.val = val; - } - - public int getChildCount() { - return 0; - } - - public SimpleTreeNode getChild(int index) { - return null; - } - - public boolean isLeaf() { - return true; - } - - public int getIndexOfChild(SimpleTreeNode child) { - return 0; - } - - public String getValue() { - if (val != null) { - return val.toString(); - } - return "NULL"; - } -} diff -r a413bcd552a4 -r 5fc51c1ecdeb agent/src/share/classes/sun/jvm/hotspot/bugspot/tree/DoubleTreeNodeAdapter.java --- a/agent/src/share/classes/sun/jvm/hotspot/bugspot/tree/DoubleTreeNodeAdapter.java Tue Mar 05 21:58:51 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,63 +0,0 @@ -/* - * Copyright (c) 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. - * - * 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 sun.jvm.hotspot.bugspot.tree; - -import sun.jvm.hotspot.debugger.cdbg.*; -import sun.jvm.hotspot.ui.tree.SimpleTreeNode; - -/** Encapsulates a double value in a tree handled by SimpleTreeModel */ - -public class DoubleTreeNodeAdapter extends FieldTreeNodeAdapter { - private double val; - - public DoubleTreeNodeAdapter(double val, FieldIdentifier id) { - this(val, id, false); - } - - public DoubleTreeNodeAdapter(double val, FieldIdentifier id, boolean treeTableMode) { - super(id, treeTableMode); - this.val = val; - } - - public int getChildCount() { - return 0; - } - - public SimpleTreeNode getChild(int index) { - return null; - } - - public boolean isLeaf() { - return true; - } - - public int getIndexOfChild(SimpleTreeNode child) { - return 0; - } - - public String getValue() { - return Double.toString(val); - } -} diff -r a413bcd552a4 -r 5fc51c1ecdeb agent/src/share/classes/sun/jvm/hotspot/bugspot/tree/EnumTreeNodeAdapter.java --- a/agent/src/share/classes/sun/jvm/hotspot/bugspot/tree/EnumTreeNodeAdapter.java Tue Mar 05 21:58:51 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,69 +0,0 @@ -/* - * Copyright (c) 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. - * - * 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 sun.jvm.hotspot.bugspot.tree; - -import sun.jvm.hotspot.debugger.cdbg.*; -import sun.jvm.hotspot.ui.tree.SimpleTreeNode; - -/** Encapsulates an enumerated value in a tree handled by SimpleTreeModel */ - -public class EnumTreeNodeAdapter extends FieldTreeNodeAdapter { - private long val; - private String enumName; - - public EnumTreeNodeAdapter(String enumName, long val, FieldIdentifier id) { - this(enumName, val, id, false); - } - - public EnumTreeNodeAdapter(String enumName, long val, FieldIdentifier id, boolean treeTableMode) { - super(id, treeTableMode); - this.enumName = enumName; - this.val = val; - } - - public int getChildCount() { - return 0; - } - - public SimpleTreeNode getChild(int index) { - return null; - } - - public boolean isLeaf() { - return true; - } - - public int getIndexOfChild(SimpleTreeNode child) { - return 0; - } - - public String getValue() { - if (enumName != null) { - return enumName; - } else { - return Long.toString(val); - } - } -} diff -r a413bcd552a4 -r 5fc51c1ecdeb agent/src/share/classes/sun/jvm/hotspot/bugspot/tree/FieldTreeNodeAdapter.java --- a/agent/src/share/classes/sun/jvm/hotspot/bugspot/tree/FieldTreeNodeAdapter.java Tue Mar 05 21:58:51 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,73 +0,0 @@ -/* - * Copyright (c) 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. - * - * 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 sun.jvm.hotspot.bugspot.tree; - -import sun.jvm.hotspot.debugger.cdbg.*; -import sun.jvm.hotspot.ui.tree.SimpleTreeNode; - -/** Abstract base class for all adapters for fields of C/C++ objects */ - -public abstract class FieldTreeNodeAdapter implements SimpleTreeNode { - private FieldIdentifier id; - private boolean treeTableMode; - - /** The identifier may be null, i.e., for the root of the tree */ - public FieldTreeNodeAdapter(FieldIdentifier id, boolean treeTableMode) { - this.id = id; - this.treeTableMode = treeTableMode; - } - - public FieldIdentifier getID() { - return id; - } - - /** Defaults to false in subclasses */ - public boolean getTreeTableMode() { - return treeTableMode; - } - - public Type getType() { - return getID().getType(); - } - - public String getName() { - if (getID() != null) { - return getID().toString(); - } - return ""; - } - - public String toString() { - if (treeTableMode) { - return getName(); - } else { - if (getID() != null) { - return getName() + ": " + getValue(); - } else { - return getValue(); - } - } - } -} diff -r a413bcd552a4 -r 5fc51c1ecdeb agent/src/share/classes/sun/jvm/hotspot/bugspot/tree/FloatTreeNodeAdapter.java --- a/agent/src/share/classes/sun/jvm/hotspot/bugspot/tree/FloatTreeNodeAdapter.java Tue Mar 05 21:58:51 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,63 +0,0 @@ -/* - * Copyright (c) 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. - * - * 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 sun.jvm.hotspot.bugspot.tree; - -import sun.jvm.hotspot.debugger.cdbg.*; -import sun.jvm.hotspot.ui.tree.SimpleTreeNode; - -/** Encapsulates a float value in a tree handled by SimpleTreeModel */ - -public class FloatTreeNodeAdapter extends FieldTreeNodeAdapter { - private float val; - - public FloatTreeNodeAdapter(float val, FieldIdentifier id) { - this(val, id, false); - } - - public FloatTreeNodeAdapter(float val, FieldIdentifier id, boolean treeTableMode) { - super(id, treeTableMode); - this.val = val; - } - - public int getChildCount() { - return 0; - } - - public SimpleTreeNode getChild(int index) { - return null; - } - - public boolean isLeaf() { - return true; - } - - public int getIndexOfChild(SimpleTreeNode child) { - return 0; - } - - public String getValue() { - return Float.toString(val); - } -} diff -r a413bcd552a4 -r 5fc51c1ecdeb agent/src/share/classes/sun/jvm/hotspot/bugspot/tree/LongTreeNodeAdapter.java --- a/agent/src/share/classes/sun/jvm/hotspot/bugspot/tree/LongTreeNodeAdapter.java Tue Mar 05 21:58:51 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,63 +0,0 @@ -/* - * Copyright (c) 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. - * - * 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 sun.jvm.hotspot.bugspot.tree; - -import sun.jvm.hotspot.debugger.cdbg.*; -import sun.jvm.hotspot.ui.tree.SimpleTreeNode; - -/** Encapsulates a long value in a tree handled by SimpleTreeModel */ - -public class LongTreeNodeAdapter extends FieldTreeNodeAdapter { - private long val; - - public LongTreeNodeAdapter(long val, FieldIdentifier id) { - this(val, id, false); - } - - public LongTreeNodeAdapter(long val, FieldIdentifier id, boolean treeTableMode) { - super(id, treeTableMode); - this.val = val; - } - - public int getChildCount() { - return 0; - } - - public SimpleTreeNode getChild(int index) { - return null; - } - - public boolean isLeaf() { - return true; - } - - public int getIndexOfChild(SimpleTreeNode child) { - return 0; - } - - public String getValue() { - return Long.toString(val); - } -} diff -r a413bcd552a4 -r 5fc51c1ecdeb agent/src/share/classes/sun/jvm/hotspot/bugspot/tree/ObjectTreeNodeAdapter.java --- a/agent/src/share/classes/sun/jvm/hotspot/bugspot/tree/ObjectTreeNodeAdapter.java Tue Mar 05 21:58:51 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,216 +0,0 @@ -/* - * Copyright (c) 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. - * - * 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 sun.jvm.hotspot.bugspot.tree; - -import java.io.*; -import sun.jvm.hotspot.debugger.*; -import sun.jvm.hotspot.debugger.cdbg.*; -import sun.jvm.hotspot.ui.tree.SimpleTreeNode; - -/** An adapter class which allows C/C++ objects to be displayed in a - tree via the SimpleTreeNode interface. */ - -public class ObjectTreeNodeAdapter extends FieldTreeNodeAdapter { - // Address of object - private Address addr; - - /** The address may be null (for object fields of objcets which are - null). The FieldIdentifier should not be null. treeTableMode - defaults to false. */ - public ObjectTreeNodeAdapter(Address addr, FieldIdentifier id) { - this(addr, id, false); - } - - /** The address may be null (for object fields of objcets which are - null). The FieldIdentifier should not be null. */ - public ObjectTreeNodeAdapter(Address addr, FieldIdentifier id, boolean treeTableMode) { - super(id, treeTableMode); - this.addr = addr; - } - - public int getChildCount() { - if (addr == null) { - return 0; - } - - Counter c = new Counter(); - getType().iterateObject(addr, c); - return c.getNumFields(); - } - - public SimpleTreeNode getChild(int index) { - if (addr == null) { - return null; - } - - Fetcher f = new Fetcher(index); - getType().iterateObject(addr, f); - return f.getChild(); - } - - public boolean isLeaf() { - return (addr == null); - } - - public int getIndexOfChild(SimpleTreeNode child) { - FieldIdentifier id = ((FieldTreeNodeAdapter) child).getID(); - Finder f = new Finder(id); - getType().iterateObject(addr, f); - return f.getIndex(); - } - - public String getValue() { - if (addr != null) { - return addr.toString(); - } - return "NULL"; - } - - /** Should be used only once, then have the number of fields - fetched. */ - static class Counter extends DefaultObjectVisitor { - private int numFields; - - public int getNumFields() { - return numFields; - } - - public void doBit(FieldIdentifier f, long val) { ++numFields; } - public void doInt(FieldIdentifier f, long val) { ++numFields; } - public void doEnum(FieldIdentifier f, long val, String enumName) { ++numFields; } - public void doFloat(FieldIdentifier f, float val) { ++numFields; } - public void doDouble(FieldIdentifier f, double val) { ++numFields; } - public void doPointer(FieldIdentifier f, Address val) { ++numFields; } - public void doArray(FieldIdentifier f, Address val) { ++numFields; } - public void doRef(FieldIdentifier f, Address val) { ++numFields; } - public void doCompound(FieldIdentifier f, Address addr) { ++numFields; } - } - - /** Creates a new SimpleTreeNode for the given field. */ - class Fetcher extends DefaultObjectVisitor { - private int index; - private int curField; - private SimpleTreeNode child; - - public Fetcher(int index) { - this.index = index; - } - - public SimpleTreeNode getChild() { - return child; - } - - public void doBit(FieldIdentifier f, long val) { - if (curField == index) { - child = new LongTreeNodeAdapter(val, f, getTreeTableMode()); - } - ++curField; - } - - public void doInt(FieldIdentifier f, long val) { - if (curField == index) { - child = new LongTreeNodeAdapter(val, f, getTreeTableMode()); - } - ++curField; - } - - public void doEnum(FieldIdentifier f, long val, String enumName) { - if (curField == index) { - child = new EnumTreeNodeAdapter(enumName, val, f, getTreeTableMode()); - } - ++curField; - } - - public void doFloat(FieldIdentifier f, float val) { - if (curField == index) { - child = new FloatTreeNodeAdapter(val, f, getTreeTableMode()); - } - ++curField; - } - - public void doDouble(FieldIdentifier f, double val) { - if (curField == index) { - child = new DoubleTreeNodeAdapter(val, f, getTreeTableMode()); - } - ++curField; - } - - public void doPointer(FieldIdentifier f, Address val) { - if (curField == index) { - child = new AddressTreeNodeAdapter(val, f, getTreeTableMode()); - } - ++curField; - } - - public void doArray(FieldIdentifier f, Address val) { - if (curField == index) { - child = new AddressTreeNodeAdapter(val, f, getTreeTableMode()); - } - ++curField; - } - - public void doRef(FieldIdentifier f, Address val) { - if (curField == index) { - child = new AddressTreeNodeAdapter(val, f, getTreeTableMode()); - } - ++curField; - } - - public void doCompound(FieldIdentifier f, Address val) { - if (curField == index) { - child = new ObjectTreeNodeAdapter(val, f, getTreeTableMode()); - } - ++curField; - } - } - - /** Finds the index of the given FieldIdentifier. */ - static class Finder extends DefaultObjectVisitor { - private FieldIdentifier id; - private int curField; - private int index = -1; - - public Finder(FieldIdentifier id) { - this.id = id; - } - - /** Returns -1 if not found */ - public int getIndex() { - return index; - } - - public void doBit(FieldIdentifier f, long val) { if (f.equals(id)) { index = curField; } ++curField; } - public void doInt(FieldIdentifier f, long val) { if (f.equals(id)) { index = curField; } ++curField; } - public void doEnum(FieldIdentifier f, long val, - String enumName) { if (f.equals(id)) { index = curField; } ++curField; } - public void doFloat(FieldIdentifier f, float val) { if (f.equals(id)) { index = curField; } ++curField; } - public void doDouble(FieldIdentifier f, double val) { if (f.equals(id)) { index = curField; } ++curField; } - public void doPointer(FieldIdentifier f, Address val) { if (f.equals(id)) { index = curField; } ++curField; } - public void doArray(FieldIdentifier f, Address val) { if (f.equals(id)) { index = curField; } ++curField; } - public void doRef(FieldIdentifier f, Address val) { if (f.equals(id)) { index = curField; } ++curField; } - public void doCompound(FieldIdentifier f, - Address val) { if (f.equals(id)) { index = curField; } ++curField; } - } -} diff -r a413bcd552a4 -r 5fc51c1ecdeb agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/BsdDebugger.java --- a/agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/BsdDebugger.java Tue Mar 05 21:58:51 2013 +0100 +++ b/agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/BsdDebugger.java Tue Mar 05 23:44:54 2013 +0100 @@ -49,7 +49,7 @@ public BsdAddress readCompKlassAddress(long address) throws DebuggerException; public BsdOopHandle readOopHandle(long address) throws DebuggerException; public BsdOopHandle readCompOopHandle(long address) throws DebuggerException; - public long[] getThreadIntegerRegisterSet(int lwp_id) throws DebuggerException; + public long[] getThreadIntegerRegisterSet(long unique_thread_id) throws DebuggerException; public long getAddressValue(Address addr) throws DebuggerException; public Address newAddress(long value) throws DebuggerException; diff -r a413bcd552a4 -r 5fc51c1ecdeb agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/BsdDebuggerLocal.java --- a/agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/BsdDebuggerLocal.java Tue Mar 05 21:58:51 2013 +0100 +++ b/agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/BsdDebuggerLocal.java Tue Mar 05 23:44:54 2013 +0100 @@ -90,7 +90,7 @@ throws DebuggerException; private native ClosestSymbol lookupByAddress0(long address) throws DebuggerException; - private native long[] getThreadIntegerRegisterSet0(int lwp_id) + private native long[] getThreadIntegerRegisterSet0(long unique_thread_id) throws DebuggerException; private native byte[] readBytesFromProcess0(long address, long numBytes) throws DebuggerException; @@ -400,10 +400,15 @@ // /** From the ThreadAccess interface via Debugger and JVMDebugger */ + public ThreadProxy getThreadForIdentifierAddress(Address threadIdAddr, Address uniqueThreadIdAddr) { + return new BsdThread(this, threadIdAddr, uniqueThreadIdAddr); + } + @Override public ThreadProxy getThreadForIdentifierAddress(Address addr) { - return new BsdThread(this, addr); + throw new RuntimeException("unimplemented"); } + /** From the ThreadAccess interface via Debugger and JVMDebugger */ public ThreadProxy getThreadForThreadId(long id) { return new BsdThread(this, id); @@ -455,22 +460,22 @@ // Thread context access // - public synchronized long[] getThreadIntegerRegisterSet(int lwp_id) + public synchronized long[] getThreadIntegerRegisterSet(long unique_thread_id) throws DebuggerException { requireAttach(); if (isCore) { - return getThreadIntegerRegisterSet0(lwp_id); + return getThreadIntegerRegisterSet0(unique_thread_id); } else { class GetThreadIntegerRegisterSetTask implements WorkerThreadTask { - int lwp_id; + long unique_thread_id; long[] result; public void doit(BsdDebuggerLocal debugger) { - result = debugger.getThreadIntegerRegisterSet0(lwp_id); + result = debugger.getThreadIntegerRegisterSet0(unique_thread_id); } } GetThreadIntegerRegisterSetTask task = new GetThreadIntegerRegisterSetTask(); - task.lwp_id = lwp_id; + task.unique_thread_id = unique_thread_id; workerThread.execute(task); return task.result; } diff -r a413bcd552a4 -r 5fc51c1ecdeb agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/BsdThread.java --- a/agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/BsdThread.java Tue Mar 05 21:58:51 2013 +0100 +++ b/agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/BsdThread.java Tue Mar 05 23:44:54 2013 +0100 @@ -28,21 +28,23 @@ class BsdThread implements ThreadProxy { private BsdDebugger debugger; - private int lwp_id; + private int thread_id; + private long unique_thread_id; /** The address argument must be the address of the _thread_id in the OSThread. It's value is result ::gettid() call. */ - BsdThread(BsdDebugger debugger, Address addr) { + BsdThread(BsdDebugger debugger, Address threadIdAddr, Address uniqueThreadIdAddr) { this.debugger = debugger; // FIXME: size of data fetched here should be configurable. // However, making it so would produce a dependency on the "types" // package from the debugger package, which is not desired. - this.lwp_id = (int) addr.getCIntegerAt(0, 4, true); + this.thread_id = (int) threadIdAddr.getCIntegerAt(0, 4, true); + this.unique_thread_id = uniqueThreadIdAddr.getCIntegerAt(0, 8, true); } BsdThread(BsdDebugger debugger, long id) { this.debugger = debugger; - this.lwp_id = (int) id; + this.thread_id = (int) id; } public boolean equals(Object obj) { @@ -50,19 +52,19 @@ return false; } - return (((BsdThread) obj).lwp_id == lwp_id); + return (((BsdThread) obj).thread_id == thread_id); } public int hashCode() { - return lwp_id; + return thread_id; } public String toString() { - return Integer.toString(lwp_id); + return Integer.toString(thread_id); } public ThreadContext getContext() throws IllegalThreadStateException { - long[] data = debugger.getThreadIntegerRegisterSet(lwp_id); + long[] data = debugger.getThreadIntegerRegisterSet(unique_thread_id); ThreadContext context = BsdThreadContextFactory.createThreadContext(debugger); for (int i = 0; i < data.length; i++) { context.setRegister(i, data[i]); diff -r a413bcd552a4 -r 5fc51c1ecdeb agent/src/share/classes/sun/jvm/hotspot/debugger/windbg/amd64/WindbgAMD64Thread.java --- a/agent/src/share/classes/sun/jvm/hotspot/debugger/windbg/amd64/WindbgAMD64Thread.java Tue Mar 05 21:58:51 2013 +0100 +++ b/agent/src/share/classes/sun/jvm/hotspot/debugger/windbg/amd64/WindbgAMD64Thread.java Tue Mar 05 23:44:54 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,21 +34,11 @@ private boolean gotID; private long id; - /** The address argument must be the address of the HANDLE of the - desired thread in the target process. */ + // The address argument must be the address of the OSThread::_thread_id WindbgAMD64Thread(WindbgDebugger debugger, Address addr) { this.debugger = debugger; - // FIXME: size of data fetched here should be configurable. - // However, making it so would produce a dependency on the "types" - // package from the debugger package, which is not desired. - - // another hack here is that we use sys thread id instead of handle. - // windbg can't get details based on handles it seems. - // I assume that osThread_win32 thread struct has _thread_id (which - // sys thread id) just after handle field. - - this.sysId = (int) addr.addOffsetTo(debugger.getAddressSize()).getCIntegerAt(0, 4, true); - gotID = false; + this.sysId = (long)addr.getCIntegerAt(0, 4, true); + gotID = false; } WindbgAMD64Thread(WindbgDebugger debugger, long sysId) { diff -r a413bcd552a4 -r 5fc51c1ecdeb agent/src/share/classes/sun/jvm/hotspot/debugger/windbg/x86/WindbgX86Thread.java --- a/agent/src/share/classes/sun/jvm/hotspot/debugger/windbg/x86/WindbgX86Thread.java Tue Mar 05 21:58:51 2013 +0100 +++ b/agent/src/share/classes/sun/jvm/hotspot/debugger/windbg/x86/WindbgX86Thread.java Tue Mar 05 23:44:54 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2003, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,21 +34,11 @@ private boolean gotID; private long id; - /** The address argument must be the address of the HANDLE of the - desired thread in the target process. */ + // The address argument must be the address of OSThread::_thread_id WindbgX86Thread(WindbgDebugger debugger, Address addr) { this.debugger = debugger; - // FIXME: size of data fetched here should be configurable. - // However, making it so would produce a dependency on the "types" - // package from the debugger package, which is not desired. - - // another hack here is that we use sys thread id instead of handle. - // windbg can't get details based on handles it seems. - // I assume that osThread_win32 thread struct has _thread_id (which - // sys thread id) just after handle field. - - this.sysId = (int) addr.addOffsetTo(debugger.getAddressSize()).getCIntegerAt(0, 4, true); - gotID = false; + this.sysId = (long)addr.getCIntegerAt(0, 4, true); + gotID = false; } WindbgX86Thread(WindbgDebugger debugger, long sysId) { diff -r a413bcd552a4 -r 5fc51c1ecdeb agent/src/share/classes/sun/jvm/hotspot/livejvm/BreakpointEvent.java --- a/agent/src/share/classes/sun/jvm/hotspot/livejvm/BreakpointEvent.java Tue Mar 05 21:58:51 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,51 +0,0 @@ -/* - * Copyright (c) 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. - * - * 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 sun.jvm.hotspot.livejvm; - -import sun.jvm.hotspot.oops.*; -import sun.jvm.hotspot.runtime.*; - -public class BreakpointEvent extends Event { - private Oop thread; - private Oop clazz; - private JNIid method; - private int location; - - public BreakpointEvent(Oop thread, - Oop clazz, - JNIid method, - int location) { - super(Event.Type.BREAKPOINT); - this.thread = thread; - this.clazz = clazz; - this.method = method; - this.location = location; - } - - public Oop thread() { return thread; } - public Oop clazz() { return clazz; } - public JNIid methodID() { return method; } - public int location() { return location; } -} diff -r a413bcd552a4 -r 5fc51c1ecdeb agent/src/share/classes/sun/jvm/hotspot/livejvm/CIntegerAccessor.java --- a/agent/src/share/classes/sun/jvm/hotspot/livejvm/CIntegerAccessor.java Tue Mar 05 21:58:51 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,47 +0,0 @@ -/* - * Copyright (c) 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. - * - * 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 sun.jvm.hotspot.livejvm; - -import sun.jvm.hotspot.debugger.*; - -class CIntegerAccessor { - private Address addr; - private long numBytes; - private boolean isUnsigned; - - CIntegerAccessor(Address addr, long numBytes, boolean isUnsigned) { - this.addr = addr; - this.numBytes = numBytes; - this.isUnsigned = isUnsigned; - } - - long getValue() { - return addr.getCIntegerAt(0, numBytes, isUnsigned); - } - - void setValue(long value) { - addr.setCIntegerAt(0, numBytes, value); - } -} diff -r a413bcd552a4 -r 5fc51c1ecdeb agent/src/share/classes/sun/jvm/hotspot/livejvm/CStringAccessor.java --- a/agent/src/share/classes/sun/jvm/hotspot/livejvm/CStringAccessor.java Tue Mar 05 21:58:51 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,69 +0,0 @@ -/* - * Copyright (c) 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. - * - * 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 sun.jvm.hotspot.livejvm; - -import java.io.UnsupportedEncodingException; -import sun.jvm.hotspot.debugger.*; - -class CStringAccessor { - private Address addr; - private int bufLen; - - CStringAccessor(Address addr, int bufLen) { - this.addr = addr; - this.bufLen = bufLen; - } - - String getValue() throws DebuggerException { - int len = 0; - while ((addr.getCIntegerAt(len, 1, true) != 0) && (len < bufLen)) { - ++len; - } - byte[] res = new byte[len]; - for (int i = 0; i < len; i++) { - res[i] = (byte) addr.getCIntegerAt(i, 1, true); - } - try { - return new String(res, "US-ASCII"); - } catch (UnsupportedEncodingException e) { - throw new DebuggerException("Unable to use US-ASCII encoding"); - } - } - - void setValue(String value) throws DebuggerException { - try { - byte[] data = value.getBytes("US-ASCII"); - if (data.length >= bufLen) { - throw new DebuggerException("String too long"); - } - for (int i = 0; i < data.length; i++) { - addr.setCIntegerAt(i, 1, data[i]); - } - addr.setCIntegerAt(data.length, 1, 0); - } catch (UnsupportedEncodingException e) { - throw new DebuggerException("Unable to use US-ASCII encoding"); - } - } -} diff -r a413bcd552a4 -r 5fc51c1ecdeb agent/src/share/classes/sun/jvm/hotspot/livejvm/Event.java --- a/agent/src/share/classes/sun/jvm/hotspot/livejvm/Event.java Tue Mar 05 21:58:51 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,41 +0,0 @@ -/* - * Copyright (c) 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. - * - * 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 sun.jvm.hotspot.livejvm; - -public class Event { - public static class Type { - private Type() {} - public static final Type BREAKPOINT = new Type(); - public static final Type EXCEPTION = new Type(); - } - - private Type type; - - public Event(Type type) { - this.type = type; - } - - public Type getType() { return type; } -} diff -r a413bcd552a4 -r 5fc51c1ecdeb agent/src/share/classes/sun/jvm/hotspot/livejvm/ExceptionEvent.java --- a/agent/src/share/classes/sun/jvm/hotspot/livejvm/ExceptionEvent.java Tue Mar 05 21:58:51 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,67 +0,0 @@ -/* - * Copyright (c) 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. - * - * 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 sun.jvm.hotspot.livejvm; - -import sun.jvm.hotspot.oops.*; -import sun.jvm.hotspot.runtime.*; - -public class ExceptionEvent extends Event { - private Oop thread; - private Oop clazz; - private JNIid method; - private int location; - private Oop exception; - private Oop catchClass; - private JNIid catchMethod; - private int catchLocation; - - public ExceptionEvent(Oop thread, - Oop clazz, - JNIid method, - int location, - Oop exception, - Oop catchClass, - JNIid catchMethod, - int catchLocation) { - super(Event.Type.EXCEPTION); - this.thread = thread; - this.clazz = clazz; - this.method = method; - this.location = location; - this.exception = exception; - this.catchClass = catchClass; - this.catchMethod = catchMethod; - this.catchLocation = catchLocation; - } - - public Oop thread() { return thread; } - public Oop clazz() { return clazz; } - public JNIid methodID() { return method; } - public int location() { return location; } - public Oop exception() { return exception; } - public Oop catchClass() { return catchClass; } - public JNIid catchMethodID() { return catchMethod; } - public int catchLocation() { return catchLocation; } -} diff -r a413bcd552a4 -r 5fc51c1ecdeb agent/src/share/classes/sun/jvm/hotspot/livejvm/JNIHandleAccessor.java --- a/agent/src/share/classes/sun/jvm/hotspot/livejvm/JNIHandleAccessor.java Tue Mar 05 21:58:51 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,54 +0,0 @@ -/* - * Copyright (c) 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. - * - * 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 sun.jvm.hotspot.livejvm; - -import sun.jvm.hotspot.debugger.*; -import sun.jvm.hotspot.oops.*; -import sun.jvm.hotspot.utilities.*; - -class JNIHandleAccessor { - private Address addr; - private ObjectHeap heap; - - JNIHandleAccessor(Address addr, ObjectHeap heap) { - this.addr = addr; - this.heap = heap; - } - - Oop getValue() { - // Accessing the contents of the JNIHandle is a double dereference - Address handle = addr.getAddressAt(0); - if (handle == null) return null; - return heap.newOop(handle.getOopHandleAt(0)); - } - - void setValue(Oop value) { - Address handle = addr.getAddressAt(0); - if (Assert.ASSERTS_ENABLED) { - Assert.that(handle != null, "Must have valid global JNI handle for setting"); - } - handle.setOopHandleAt(0, value.getHandle()); - } -} diff -r a413bcd552a4 -r 5fc51c1ecdeb agent/src/share/classes/sun/jvm/hotspot/livejvm/ServiceabilityAgentJVMDIModule.java --- a/agent/src/share/classes/sun/jvm/hotspot/livejvm/ServiceabilityAgentJVMDIModule.java Tue Mar 05 21:58:51 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,415 +0,0 @@ -/* - * Copyright (c) 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. - * - * 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 sun.jvm.hotspot.livejvm; - -import sun.jvm.hotspot.debugger.*; -import sun.jvm.hotspot.oops.*; -import sun.jvm.hotspot.runtime.*; - -/** Provides Java programming language-level interaction with a live - Java HotSpot VM via the use of the SA's JVMDI module. This is an - experimental mechanism. The BugSpot debugger should be converted - to use the JVMDI/JDWP-based JDI implementation for live process - interaction once the JDI binding for the SA is complete. */ - -public class ServiceabilityAgentJVMDIModule { - private Debugger dbg; - private String[] saLibNames; - private String saLibName; - private boolean attached; - - private boolean suspended; - - private static final int JVMDI_EVENT_BREAKPOINT = 2; - private static final int JVMDI_EVENT_EXCEPTION = 4; - - private static long timeoutMillis = 3000; - - // Values in target process - // Events sent from VM to SA - private CIntegerAccessor saAttached; - private CIntegerAccessor saEventPending; - private CIntegerAccessor saEventKind; - // Exception events - private JNIHandleAccessor saExceptionThread; - private JNIHandleAccessor saExceptionClass; - private JNIid saExceptionMethod; - private CIntegerAccessor saExceptionLocation; - private JNIHandleAccessor saExceptionException; - private JNIHandleAccessor saExceptionCatchClass; - private JNIid saExceptionCatchMethod; - private CIntegerAccessor saExceptionCatchLocation; - // Breakpoint events - private JNIHandleAccessor saBreakpointThread; - private JNIHandleAccessor saBreakpointClass; - private JNIid saBreakpointMethod; - private CIntegerAccessor saBreakpointLocation; - // Commands sent by the SA to the VM - private int SA_CMD_SUSPEND_ALL; - private int SA_CMD_RESUME_ALL; - private int SA_CMD_TOGGLE_BREAKPOINT; - private int SA_CMD_BUF_SIZE; - private CIntegerAccessor saCmdPending; - private CIntegerAccessor saCmdType; - private CIntegerAccessor saCmdResult; - private CStringAccessor saCmdResultErrMsg; - // Toggle breakpoint command arguments - private CStringAccessor saCmdBkptSrcFileName; - private CStringAccessor saCmdBkptPkgName; - private CIntegerAccessor saCmdBkptLineNumber; - private CIntegerAccessor saCmdBkptResWasError; - private CIntegerAccessor saCmdBkptResLineNumber; - private CIntegerAccessor saCmdBkptResBCI; - private CIntegerAccessor saCmdBkptResWasSet; - private CStringAccessor saCmdBkptResMethodName; - private CStringAccessor saCmdBkptResMethodSig; - - public ServiceabilityAgentJVMDIModule(Debugger dbg, String[] saLibNames) { - this.dbg = dbg; - this.saLibNames = saLibNames; - } - - /** Indicates whether a call to attach() should complete without an - exception. */ - public boolean canAttach() { - return setupLookup("SA_CMD_SUSPEND_ALL"); - } - - /** Attempt to initiate a connection with the JVMDI module in the - target VM. */ - public void attach() throws DebuggerException { - if (!canAttach()) { - throw new DebuggerException("Unable to initiate symbol lookup in SA's JVMDI module"); - } - - if (attached) { - throw new DebuggerException("Already attached"); - } - - // Attempt to look up well-known symbols in the target VM. - SA_CMD_SUSPEND_ALL = lookupConstInt("SA_CMD_SUSPEND_ALL"); - SA_CMD_RESUME_ALL = lookupConstInt("SA_CMD_RESUME_ALL"); - SA_CMD_TOGGLE_BREAKPOINT = lookupConstInt("SA_CMD_TOGGLE_BREAKPOINT"); - SA_CMD_BUF_SIZE = lookupConstInt("SA_CMD_BUF_SIZE"); - - saAttached = lookupCInt("saAttached"); - saEventPending = lookupCInt("saEventPending"); - saEventKind = lookupCInt("saEventKind"); - saCmdPending = lookupCInt("saCmdPending"); - saCmdType = lookupCInt("saCmdType"); - saCmdResult = lookupCInt("saCmdResult"); - saCmdResultErrMsg = lookupCString("saCmdResultErrMsg", SA_CMD_BUF_SIZE); - // Toggling of breakpoints - saCmdBkptSrcFileName = lookupCString("saCmdBkptSrcFileName", SA_CMD_BUF_SIZE); - saCmdBkptPkgName = lookupCString("saCmdBkptPkgName", SA_CMD_BUF_SIZE); - saCmdBkptLineNumber = lookupCInt("saCmdBkptLineNumber"); - saCmdBkptResWasError = lookupCInt("saCmdBkptResWasError"); - saCmdBkptResLineNumber = lookupCInt("saCmdBkptResLineNumber"); - saCmdBkptResBCI = lookupCInt("saCmdBkptResBCI"); - saCmdBkptResWasSet = lookupCInt("saCmdBkptResWasSet"); - saCmdBkptResMethodName = lookupCString("saCmdBkptResMethodName", SA_CMD_BUF_SIZE); - saCmdBkptResMethodSig = lookupCString("saCmdBkptResMethodSig", SA_CMD_BUF_SIZE); - - // Check for existence of symbols needed later - // FIXME: should probably cache these since we can't support the - // -Xrun module or the VM getting unloaded anyway - lookup("saExceptionThread"); - lookup("saExceptionClass"); - lookup("saExceptionMethod"); - lookup("saExceptionLocation"); - lookup("saExceptionException"); - lookup("saExceptionCatchClass"); - lookup("saExceptionCatchMethod"); - lookup("saExceptionCatchLocation"); - lookup("saBreakpointThread"); - lookup("saBreakpointClass"); - lookup("saBreakpointMethod"); - lookup("saBreakpointLocation"); - - saAttached.setValue(1); - attached = true; - } - - public void detach() { - saAttached.setValue(0); - attached = false; - saLibName = null; - } - - /** Set the timeout value (in milliseconds) for the VM to reply to - commands. Once this timeout has elapsed, the VM is assumed to - have disconnected. Defaults to 3000 milliseconds (3 seconds). */ - public void setCommandTimeout(long millis) { - timeoutMillis = millis; - } - - /** Get the timeout value (in milliseconds) for the VM to reply to - commands. Once this timeout has elapsed, the VM is assumed to - have disconnected. Defaults to 3000 milliseconds (3 seconds). */ - public long getCommandTimeout() { - return timeoutMillis; - } - - /** Indicates whether a Java debug event is pending */ - public boolean eventPending() { - return (saEventPending.getValue() != 0); - } - - /** Poll for event; returns null if none pending. */ - public Event eventPoll() { - if (saEventPending.getValue() == 0) { - return null; - } - - int kind = (int) saEventKind.getValue(); - switch (kind) { - case JVMDI_EVENT_EXCEPTION: { - JNIHandleAccessor thread = lookupJNIHandle("saExceptionThread"); - JNIHandleAccessor clazz = lookupJNIHandle("saExceptionClass"); - JNIid method = lookupJNIid("saExceptionMethod"); - CIntegerAccessor location = lookupCInt("saExceptionLocation"); - JNIHandleAccessor exception = lookupJNIHandle("saExceptionException"); - JNIHandleAccessor catchClass = lookupJNIHandle("saExceptionCatchClass"); - JNIid catchMethod = lookupJNIid("saExceptionCatchMethod"); - CIntegerAccessor catchLocation = lookupCInt("saExceptionCatchLocation"); - return new ExceptionEvent(thread.getValue(), clazz.getValue(), method, - (int) location.getValue(), exception.getValue(), - catchClass.getValue(), catchMethod, (int) catchLocation.getValue()); - } - - case JVMDI_EVENT_BREAKPOINT: { - JNIHandleAccessor thread = lookupJNIHandle("saBreakpointThread"); - JNIHandleAccessor clazz = lookupJNIHandle("saBreakpointClass"); - JNIid method = lookupJNIid("saBreakpointMethod"); - CIntegerAccessor location = lookupCInt("saBreakpointLocation"); - return new BreakpointEvent(thread.getValue(), clazz.getValue(), - method, (int) location.getValue()); - } - - default: - throw new DebuggerException("Unsupported event type " + kind); - } - } - - /** Continue past current event */ - public void eventContinue() { - saEventPending.setValue(0); - } - - /** Suspend all Java threads in the target VM. Throws - DebuggerException if the VM disconnected. */ - public void suspend() { - saCmdType.setValue(SA_CMD_SUSPEND_ALL); - saCmdPending.setValue(1); - waitForCommandCompletion(); - suspended = true; - } - - /** Resume all Java threads in the target VM. Throws - DebuggerException if the VM disconnected. */ - public void resume() { - saCmdType.setValue(SA_CMD_RESUME_ALL); - saCmdPending.setValue(1); - waitForCommandCompletion(); - suspended = false; - } - - /** Indicates whether all Java threads have been suspended via this - interface. */ - public boolean isSuspended() { - return suspended; - } - - /** Information about toggling of breakpoints */ - public static class BreakpointToggleResult { - private boolean success; - private String errMsg; - private int lineNumber; - private int bci; - private boolean wasSet; - private String methodName; - private String methodSig; - - /** Success constructor */ - public BreakpointToggleResult(int lineNumber, int bci, boolean wasSet, - String methodName, String methodSig) { - this.lineNumber = lineNumber; - this.bci = bci; - this.wasSet = wasSet; - this.methodName = methodName; - this.methodSig = methodSig; - success = true; - } - - /** Failure constructor */ - public BreakpointToggleResult(String errMsg) { - this.errMsg = errMsg; - success = false; - } - - /** Indicates whether this represents a successful return or not */ - public boolean getSuccess() { return success; } - - /** Valid only if getSuccess() returns false */ - public String getErrMsg() { return errMsg; } - - /** Line number at which breakpoint toggle occurred; valid only if - getSuccess() returns true. */ - public int getLineNumber() { return lineNumber; } - - /** BCI at which breakpoint toggle occurred; valid only if - getSuccess() returns true. */ - public int getBCI() { return bci; } - - /** Indicates whether the breakpoint toggle was the set of a - breakpoint or not; valid only if getSuccess() returns true. */ - public boolean getWasSet() { return wasSet; } - - /** Method name in which the breakpoint toggle occurred; valid - only if getSuccess() returns true. */ - public String getMethodName() { return methodName; } - - /** Method signature in which the breakpoint toggle occurred; - valid only if getSuccess() returns true. */ - public String getMethodSignature() { return methodSig; } - } - - /** Toggle a breakpoint. Throws DebuggerException if a real error - occurred; otherwise returns non-null BreakpointToggleResult. The - work of scanning the loaded classes is done in the target VM - because it turns out to be significantly faster than scanning - through the system dictionary from the SA, and interactivity - when setting breakpoints is important. */ - public BreakpointToggleResult toggleBreakpoint(String srcFileName, - String pkgName, - int lineNo) { - saCmdBkptSrcFileName.setValue(srcFileName); - saCmdBkptPkgName.setValue(pkgName); - saCmdBkptLineNumber.setValue(lineNo); - saCmdType.setValue(SA_CMD_TOGGLE_BREAKPOINT); - saCmdPending.setValue(1); - if (waitForCommandCompletion(true)) { - return new BreakpointToggleResult((int) saCmdBkptResLineNumber.getValue(), - (int) saCmdBkptResBCI.getValue(), - (saCmdBkptResWasSet.getValue() != 0), - saCmdBkptResMethodName.getValue(), - saCmdBkptResMethodSig.getValue()); - } else { - return new BreakpointToggleResult(saCmdResultErrMsg.getValue()); - } - } - - - //---------------------------------------------------------------------- - // Internals only below this point - // - - private CIntegerAccessor lookupCInt(String symbolName) { - return new CIntegerAccessor(lookup(symbolName), 4, false); - } - - private CStringAccessor lookupCString(String symbolName, int bufLen) { - return new CStringAccessor(lookup(symbolName), bufLen); - } - - private JNIHandleAccessor lookupJNIHandle(String symbolName) { - return new JNIHandleAccessor(lookup(symbolName), VM.getVM().getObjectHeap()); - } - - private JNIid lookupJNIid(String symbolName) { - Address idAddr = lookup(symbolName).getAddressAt(0); - if (idAddr == null) { - return null; - } - return new JNIid(idAddr, VM.getVM().getObjectHeap()); - } - - private int lookupConstInt(String symbolName) { - Address addr = lookup(symbolName); - return (int) addr.getCIntegerAt(0, 4, false); - } - - private boolean setupLookup(String symbolName) { - if (saLibName == null) { - for (int i = 0; i < saLibNames.length; i++) { - Address addr = dbg.lookup(saLibNames[i], symbolName); - if (addr != null) { - saLibName = saLibNames[i]; - return true; - } - } - return false; - } - return true; - } - - private Address lookup(String symbolName) { - if (saLibName == null) { - for (int i = 0; i < saLibNames.length; i++) { - Address addr = dbg.lookup(saLibNames[i], symbolName); - if (addr != null) { - saLibName = saLibNames[i]; - return addr; - } - } - throw new DebuggerException("Unable to find symbol " + symbolName + " in any of the known names for the SA"); - } - - Address addr = dbg.lookup(saLibName, symbolName); - if (addr == null) { - throw new DebuggerException("Unable to find symbol " + symbolName + " in " + saLibName); - } - return addr; - } - - private void waitForCommandCompletion() { - waitForCommandCompletion(false); - } - - /** Returns true if command succeeded, false if not */ - private boolean waitForCommandCompletion(boolean forBreakpoint) { - long start = System.currentTimeMillis(); - long cur = start; - while ((saCmdPending.getValue() != 0) && - (cur - start < timeoutMillis)) { - try { - java.lang.Thread.currentThread().sleep(10); - } catch (InterruptedException e) { - } - cur = System.currentTimeMillis(); - } - if (saCmdPending.getValue() != 0) { - detach(); - throw new DebuggerException("VM appears to have died"); - } - boolean succeeded = saCmdResult.getValue() == 0; - if (!succeeded && - (!forBreakpoint || saCmdBkptResWasError.getValue() != 0)) { - String err = saCmdResultErrMsg.getValue(); - throw new DebuggerException("Error executing JVMDI command: " + err); - } - return succeeded; - } -} diff -r a413bcd552a4 -r 5fc51c1ecdeb agent/src/share/classes/sun/jvm/hotspot/memory/AFLBinaryTreeDictionary.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/agent/src/share/classes/sun/jvm/hotspot/memory/AFLBinaryTreeDictionary.java Tue Mar 05 23:44:54 2013 +0100 @@ -0,0 +1,59 @@ +/* + * @(#)BinaryTreeDictionary.java + * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package sun.jvm.hotspot.memory; + +import java.util.*; +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.types.*; +import sun.jvm.hotspot.runtime.*; + +public class AFLBinaryTreeDictionary extends VMObject { + static { + VM.registerVMInitializedObserver(new Observer() { + public void update(Observable o, Object data) { + initialize(VM.getVM().getTypeDataBase()); + } + }); + } + + private static synchronized void initialize(TypeDataBase db) { + Type type = db.lookupType("AFLBinaryTreeDictionary"); + totalSizeField = type.getCIntegerField("_total_size"); + } + + // Fields + private static CIntegerField totalSizeField; + + // Accessors + public long size() { + return totalSizeField.getValue(addr); + } + + // Constructor + public AFLBinaryTreeDictionary(Address addr) { + super(addr); + } +} diff -r a413bcd552a4 -r 5fc51c1ecdeb agent/src/share/classes/sun/jvm/hotspot/memory/BinaryTreeDictionary.java --- a/agent/src/share/classes/sun/jvm/hotspot/memory/BinaryTreeDictionary.java Tue Mar 05 21:58:51 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,59 +0,0 @@ -/* - * @(#)BinaryTreeDictionary.java - * Copyright (c) 2000, 2008, 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 sun.jvm.hotspot.memory; - -import java.util.*; -import sun.jvm.hotspot.debugger.*; -import sun.jvm.hotspot.types.*; -import sun.jvm.hotspot.runtime.*; - -public class BinaryTreeDictionary extends VMObject { - static { - VM.registerVMInitializedObserver(new Observer() { - public void update(Observable o, Object data) { - initialize(VM.getVM().getTypeDataBase()); - } - }); - } - - private static synchronized void initialize(TypeDataBase db) { - Type type = db.lookupType("BinaryTreeDictionary"); - totalSizeField = type.getCIntegerField("_totalSize"); - } - - // Fields - private static CIntegerField totalSizeField; - - // Accessors - public long size() { - return totalSizeField.getValue(addr); - } - - // Constructor - public BinaryTreeDictionary(Address addr) { - super(addr); - } -} diff -r a413bcd552a4 -r 5fc51c1ecdeb agent/src/share/classes/sun/jvm/hotspot/memory/CMSCollector.java --- a/agent/src/share/classes/sun/jvm/hotspot/memory/CMSCollector.java Tue Mar 05 21:58:51 2013 +0100 +++ b/agent/src/share/classes/sun/jvm/hotspot/memory/CMSCollector.java Tue Mar 05 23:44:54 2013 +0100 @@ -61,15 +61,13 @@ CMSBitMap markBitMap = markBitMap(); long addressSize = VM.getVM().getAddressSize(); if ( markBitMap.isMarked(addr) && markBitMap.isMarked(addr.addOffsetTo(1*addressSize)) ) { - System.err.println("Printezis bits are set..."); Address nextOneAddr = markBitMap.getNextMarkedWordAddress(addr.addOffsetTo(2*addressSize)); //return size in bytes long size = (nextOneAddr.addOffsetTo(1*addressSize)).minus(addr); return size; } else { - //missing Printezis marks - System.err.println("Missing Printszis marks..."); - return -1; + //missing Printezis marks + return -1; } } diff -r a413bcd552a4 -r 5fc51c1ecdeb agent/src/share/classes/sun/jvm/hotspot/memory/CompactibleFreeListSpace.java --- a/agent/src/share/classes/sun/jvm/hotspot/memory/CompactibleFreeListSpace.java Tue Mar 05 21:58:51 2013 +0100 +++ b/agent/src/share/classes/sun/jvm/hotspot/memory/CompactibleFreeListSpace.java Tue Mar 05 23:44:54 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -117,9 +117,9 @@ } // large block - BinaryTreeDictionary bfbd = (BinaryTreeDictionary) VMObjectFactory.newObject(BinaryTreeDictionary.class, + AFLBinaryTreeDictionary aflbd = (AFLBinaryTreeDictionary) VMObjectFactory.newObject(AFLBinaryTreeDictionary.class, dictionaryField.getValue(addr)); - size += bfbd.size(); + size += aflbd.size(); // linear block in TLAB @@ -191,7 +191,6 @@ //Find the object size using Printezis bits and skip over long size = collector().blockSizeUsingPrintezisBits(cur); if (size == -1) { - System.err.println("Printezis bits not set..."); break; } cur = cur.addOffsetTo(adjustObjectSizeInBytes(size)); diff -r a413bcd552a4 -r 5fc51c1ecdeb agent/src/share/classes/sun/jvm/hotspot/memory/FreeList.java --- a/agent/src/share/classes/sun/jvm/hotspot/memory/FreeList.java Tue Mar 05 21:58:51 2013 +0100 +++ b/agent/src/share/classes/sun/jvm/hotspot/memory/FreeList.java Tue Mar 05 23:44:54 2013 +0100 @@ -1,7 +1,7 @@ /* * @(#)FreeList.java * - * Copyright (c) 2000, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -41,7 +41,7 @@ } private static synchronized void initialize(TypeDataBase db) { - Type type = db.lookupType("FreeList"); + Type type = db.lookupType("FreeList"); sizeField = type.getCIntegerField("_size"); countField = type.getCIntegerField("_count"); headerSize = type.getSize(); diff -r a413bcd552a4 -r 5fc51c1ecdeb agent/src/share/classes/sun/jvm/hotspot/oops/ConstMethod.java --- a/agent/src/share/classes/sun/jvm/hotspot/oops/ConstMethod.java Tue Mar 05 21:58:51 2013 +0100 +++ b/agent/src/share/classes/sun/jvm/hotspot/oops/ConstMethod.java Tue Mar 05 23:44:54 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -49,12 +49,18 @@ private static int HAS_LOCALVARIABLE_TABLE; private static int HAS_EXCEPTION_TABLE; private static int HAS_GENERIC_SIGNATURE; + private static int HAS_METHOD_ANNOTATIONS; + private static int HAS_PARAMETER_ANNOTATIONS; + private static int HAS_DEFAULT_ANNOTATIONS; + private static int HAS_TYPE_ANNOTATIONS; + + private static final int sizeofShort = 2; private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { Type type = db.lookupType("ConstMethod"); constants = new MetadataField(type.getAddressField("_constants"), 0); constMethodSize = new CIntField(type.getCIntegerField("_constMethod_size"), 0); - flags = new ByteField(type.getJByteField("_flags"), 0); + flags = new CIntField(type.getCIntegerField("_flags"), 0); // enum constants for flags HAS_LINENUMBER_TABLE = db.lookupIntConstant("ConstMethod::_has_linenumber_table").intValue(); @@ -62,6 +68,10 @@ HAS_LOCALVARIABLE_TABLE = db.lookupIntConstant("ConstMethod::_has_localvariable_table").intValue(); HAS_EXCEPTION_TABLE = db.lookupIntConstant("ConstMethod::_has_exception_table").intValue(); HAS_GENERIC_SIGNATURE = db.lookupIntConstant("ConstMethod::_has_generic_signature").intValue(); + HAS_METHOD_ANNOTATIONS = db.lookupIntConstant("ConstMethod::_has_method_annotations").intValue(); + HAS_PARAMETER_ANNOTATIONS = db.lookupIntConstant("ConstMethod::_has_parameter_annotations").intValue(); + HAS_DEFAULT_ANNOTATIONS = db.lookupIntConstant("ConstMethod::_has_default_annotations").intValue(); + HAS_TYPE_ANNOTATIONS = db.lookupIntConstant("ConstMethod::_has_type_annotations").intValue(); // Size of Java bytecodes allocated immediately after ConstMethod*. codeSize = new CIntField(type.getCIntegerField("_code_size"), 0); @@ -92,7 +102,7 @@ // Fields private static MetadataField constants; private static CIntField constMethodSize; - private static ByteField flags; + private static CIntField flags; private static CIntField codeSize; private static CIntField nameIndex; private static CIntField signatureIndex; @@ -123,7 +133,7 @@ return constMethodSize.getValue(this); } - public byte getFlags() { + public long getFlags() { return flags.getValue(this); } @@ -253,7 +263,7 @@ public void iterateFields(MetadataVisitor visitor) { visitor.doMetadata(constants, true); visitor.doCInt(constMethodSize, true); - visitor.doByte(flags, true); + visitor.doCInt(flags, true); visitor.doCInt(codeSize, true); visitor.doCInt(nameIndex, true); visitor.doCInt(signatureIndex, true); @@ -381,6 +391,22 @@ return (getFlags() & HAS_GENERIC_SIGNATURE) != 0; } + private boolean hasMethodAnnotations() { + return (getFlags() & HAS_METHOD_ANNOTATIONS) != 0; + } + + private boolean hasParameterAnnotations() { + return (getFlags() & HAS_PARAMETER_ANNOTATIONS) != 0; + } + + private boolean hasDefaultAnnotations() { + return (getFlags() & HAS_DEFAULT_ANNOTATIONS) != 0; + } + + private boolean hasTypeAnnotations() { + return (getFlags() & HAS_TYPE_ANNOTATIONS) != 0; + } + //--------------------------------------------------------------------------- // Internals only below this point @@ -400,9 +426,15 @@ return offsetOfCodeEnd() + (isNative() ? 2 * VM.getVM().getAddressSize() : 0); } - // Offset of last short in Method* + // Offset of last short in Method* before annotations, if present private long offsetOfLastU2Element() { - return getSize() * VM.getVM().getObjectHeap().getOopSize() - 2; + int offset = 0; + if (hasMethodAnnotations()) offset++; + if (hasParameterAnnotations()) offset++; + if (hasTypeAnnotations()) offset++; + if (hasDefaultAnnotations()) offset++; + long wordSize = VM.getVM().getObjectHeap().getOopSize(); + return (getSize() * wordSize) - (offset * wordSize) - sizeofShort; } // Offset of the generic signature index @@ -411,7 +443,7 @@ } private long offsetOfCheckedExceptionsLength() { - return hasGenericSignature() ? offsetOfLastU2Element() - 2 : + return hasGenericSignature() ? offsetOfLastU2Element() - sizeofShort : offsetOfLastU2Element(); } @@ -461,11 +493,11 @@ } if (hasExceptionTable()) { - return offsetOfExceptionTable() - 2; + return offsetOfExceptionTable() - sizeofShort; } else if (hasCheckedExceptions()) { - return offsetOfCheckedExceptions() - 2; + return offsetOfCheckedExceptions() - sizeofShort; } else { - return hasGenericSignature() ? offsetOfLastU2Element() - 2 : + return hasGenericSignature() ? offsetOfLastU2Element() - sizeofShort : offsetOfLastU2Element(); } } @@ -493,9 +525,9 @@ Assert.that(hasExceptionTable(), "should only be called if table is present"); } if (hasCheckedExceptions()) { - return offsetOfCheckedExceptions() - 2; + return offsetOfCheckedExceptions() - sizeofShort; } else { - return hasGenericSignature() ? offsetOfLastU2Element() - 2 : + return hasGenericSignature() ? offsetOfLastU2Element() - sizeofShort : offsetOfLastU2Element(); } } diff -r a413bcd552a4 -r 5fc51c1ecdeb agent/src/share/classes/sun/jvm/hotspot/oops/ConstantPool.java --- a/agent/src/share/classes/sun/jvm/hotspot/oops/ConstantPool.java Tue Mar 05 21:58:51 2013 +0100 +++ b/agent/src/share/classes/sun/jvm/hotspot/oops/ConstantPool.java Tue Mar 05 23:44:54 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -469,7 +469,6 @@ case JVM_CONSTANT_UnresolvedClassInError: return "JVM_CONSTANT_UnresolvedClassInError"; case JVM_CONSTANT_MethodHandleInError:return "JVM_CONSTANT_MethodHandleInError"; case JVM_CONSTANT_MethodTypeInError: return "JVM_CONSTANT_MethodTypeInError"; - case JVM_CONSTANT_Object: return "JVM_CONSTANT_Object"; } throw new InternalError("Unknown tag: " + tag); } diff -r a413bcd552a4 -r 5fc51c1ecdeb agent/src/share/classes/sun/jvm/hotspot/oops/MethodData.java --- a/agent/src/share/classes/sun/jvm/hotspot/oops/MethodData.java Tue Mar 05 21:58:51 2013 +0100 +++ b/agent/src/share/classes/sun/jvm/hotspot/oops/MethodData.java Tue Mar 05 23:44:54 2013 +0100 @@ -184,7 +184,6 @@ if (trapReasonName[index] == null) { throw new InternalError("missing reason for " + index); } - System.out.println(trapReasonName[index]); } } diff -r a413bcd552a4 -r 5fc51c1ecdeb agent/src/share/classes/sun/jvm/hotspot/oops/ObjectHeap.java --- a/agent/src/share/classes/sun/jvm/hotspot/oops/ObjectHeap.java Tue Mar 05 21:58:51 2013 +0100 +++ b/agent/src/share/classes/sun/jvm/hotspot/oops/ObjectHeap.java Tue Mar 05 23:44:54 2013 +0100 @@ -335,7 +335,6 @@ } if (obj == null) { //Find the object size using Printezis bits and skip over - System.err.println("Finding object size using Printezis bits and skipping over..."); long size = 0; if ( (cmsSpaceOld != null) && cmsSpaceOld.contains(handle) ){ @@ -467,7 +466,7 @@ liveRegions.add(tlab.start()); liveRegions.add(tlab.start()); liveRegions.add(tlab.top()); - liveRegions.add(tlab.end()); + liveRegions.add(tlab.hardEnd()); } } } diff -r a413bcd552a4 -r 5fc51c1ecdeb agent/src/share/classes/sun/jvm/hotspot/runtime/ClassConstants.java --- a/agent/src/share/classes/sun/jvm/hotspot/runtime/ClassConstants.java Tue Mar 05 21:58:51 2013 +0100 +++ b/agent/src/share/classes/sun/jvm/hotspot/runtime/ClassConstants.java Tue Mar 05 23:44:54 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -67,7 +67,6 @@ public static final int JVM_CONSTANT_UnresolvedClassInError = 103; // Error tag due to resolution error public static final int JVM_CONSTANT_MethodHandleInError = 104; // Error tag due to resolution error public static final int JVM_CONSTANT_MethodTypeInError = 105; // Error tag due to resolution error - public static final int JVM_CONSTANT_Object = 106; // Required for BoundMethodHandle arguments. // 1.5 major/minor version numbers from JVM spec. 3rd edition public static final short MAJOR_VERSION = 49; diff -r a413bcd552a4 -r 5fc51c1ecdeb agent/src/share/classes/sun/jvm/hotspot/runtime/OSThread.java --- a/agent/src/share/classes/sun/jvm/hotspot/runtime/OSThread.java Tue Mar 05 21:58:51 2013 +0100 +++ b/agent/src/share/classes/sun/jvm/hotspot/runtime/OSThread.java Tue Mar 05 23:44:54 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,6 +32,7 @@ // to the sys_thread_t structure of the classic JVM implementation. public class OSThread extends VMObject { private static JIntField interruptedField; + private static JIntField threadIdField; static { VM.registerVMInitializedObserver(new Observer() { public void update(Observable o, Object data) { @@ -43,6 +44,7 @@ private static synchronized void initialize(TypeDataBase db) { Type type = db.lookupType("OSThread"); interruptedField = type.getJIntField("_interrupted"); + threadIdField = type.getJIntField("_thread_id"); } public OSThread(Address addr) { @@ -52,4 +54,9 @@ public boolean interrupted() { return ((int)interruptedField.getValue(addr)) != 0; } + + public int threadId() { + return (int)threadIdField.getValue(addr); + } + } diff -r a413bcd552a4 -r 5fc51c1ecdeb agent/src/share/classes/sun/jvm/hotspot/runtime/ThreadLocalAllocBuffer.java --- a/agent/src/share/classes/sun/jvm/hotspot/runtime/ThreadLocalAllocBuffer.java Tue Mar 05 21:58:51 2013 +0100 +++ b/agent/src/share/classes/sun/jvm/hotspot/runtime/ThreadLocalAllocBuffer.java Tue Mar 05 23:44:54 2013 +0100 @@ -27,6 +27,7 @@ import java.io.*; import java.util.*; import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.oops.*; import sun.jvm.hotspot.types.*; /**

ThreadLocalAllocBuffer: a descriptor for thread-local storage @@ -62,9 +63,22 @@ super(addr); } - public Address start() { return startField.getValue(addr); } - public Address end() { return endField.getValue(addr); } - public Address top() { return topField.getValue(addr); } + public Address start() { return startField.getValue(addr); } + public Address end() { return endField.getValue(addr); } + public Address top() { return topField.getValue(addr); } + public Address hardEnd() { return end().addOffsetTo(alignmentReserve()); } + + private long alignmentReserve() { + return Oop.alignObjectSize(endReserve()); + } + + private long endReserve() { + long minFillerArraySize = Array.baseOffsetInBytes(BasicType.T_INT); + long reserveForAllocationPrefetch = VM.getVM().getReserveForAllocationPrefetch(); + long heapWordSize = VM.getVM().getHeapWordSize(); + + return Math.max(minFillerArraySize, reserveForAllocationPrefetch * heapWordSize); + } /** Support for iteration over heap -- not sure how this will interact with GC in reflective system, but necessary for the diff -r a413bcd552a4 -r 5fc51c1ecdeb agent/src/share/classes/sun/jvm/hotspot/runtime/VM.java --- a/agent/src/share/classes/sun/jvm/hotspot/runtime/VM.java Tue Mar 05 21:58:51 2013 +0100 +++ b/agent/src/share/classes/sun/jvm/hotspot/runtime/VM.java Tue Mar 05 23:44:54 2013 +0100 @@ -90,10 +90,6 @@ /** Flags indicating whether we are attached to a core, C1, or C2 build */ private boolean usingClientCompiler; private boolean usingServerCompiler; - /** Flag indicating whether UseTLAB is turned on */ - private boolean useTLAB; - /** Flag indicating whether invokedynamic support is on */ - private boolean enableInvokeDynamic; /** alignment constants */ private boolean isLP64; private int bytesPerLong; @@ -114,6 +110,7 @@ private int invalidOSREntryBCI; private ReversePtrs revPtrs; private VMRegImpl vmregImpl; + private int reserveForAllocationPrefetch; // System.getProperties from debuggee VM private Properties sysProps; @@ -293,6 +290,10 @@ vmRelease = CStringUtilities.getString(releaseAddr); Address vmInternalInfoAddr = vmVersion.getAddressField("_s_internal_vm_info_string").getValue(); vmInternalInfo = CStringUtilities.getString(vmInternalInfoAddr); + + CIntegerType intType = (CIntegerType) db.lookupType("int"); + CIntegerField reserveForAllocationPrefetchField = vmVersion.getCIntegerField("_reserve_for_allocation_prefetch"); + reserveForAllocationPrefetch = (int)reserveForAllocationPrefetchField.getCInteger(intType); } catch (Exception exp) { throw new RuntimeException("can't determine target's VM version : " + exp.getMessage()); } @@ -321,9 +322,6 @@ } } - useTLAB = (db.lookupIntConstant("UseTLAB").intValue() != 0); - enableInvokeDynamic = (db.lookupIntConstant("EnableInvokeDynamic").intValue() != 0); - if (debugger != null) { isLP64 = debugger.getMachineDescription().isLP64(); } @@ -574,15 +572,6 @@ } } - /** Indicates whether Thread-Local Allocation Buffers are used */ - public boolean getUseTLAB() { - return useTLAB; - } - - public boolean getEnableInvokeDynamic() { - return enableInvokeDynamic; - } - public TypeDataBase getTypeDataBase() { return db; } @@ -778,6 +767,10 @@ return vmInternalInfo; } + public int getReserveForAllocationPrefetch() { + return reserveForAllocationPrefetch; + } + public boolean isSharingEnabled() { if (sharingEnabled == null) { Flag flag = getCommandLineFlag("UseSharedSpaces"); @@ -813,6 +806,12 @@ return objectAlignmentInBytes; } + /** Indicates whether Thread-Local Allocation Buffers are used */ + public boolean getUseTLAB() { + Flag flag = getCommandLineFlag("UseTLAB"); + return (flag == null) ? false: flag.getBool(); + } + // returns null, if not available. public Flag[] getCommandLineFlags() { if (commandLineFlags == null) { diff -r a413bcd552a4 -r 5fc51c1ecdeb agent/src/share/classes/sun/jvm/hotspot/runtime/bsd_amd64/BsdAMD64JavaThreadPDAccess.java --- a/agent/src/share/classes/sun/jvm/hotspot/runtime/bsd_amd64/BsdAMD64JavaThreadPDAccess.java Tue Mar 05 21:58:51 2013 +0100 +++ b/agent/src/share/classes/sun/jvm/hotspot/runtime/bsd_amd64/BsdAMD64JavaThreadPDAccess.java Tue Mar 05 23:44:54 2013 +0100 @@ -28,6 +28,8 @@ import java.util.*; import sun.jvm.hotspot.debugger.*; import sun.jvm.hotspot.debugger.amd64.*; +import sun.jvm.hotspot.debugger.bsd.BsdDebugger; +import sun.jvm.hotspot.debugger.bsd.BsdDebuggerLocal; import sun.jvm.hotspot.runtime.*; import sun.jvm.hotspot.runtime.amd64.*; import sun.jvm.hotspot.runtime.x86.*; @@ -38,8 +40,9 @@ private static AddressField lastJavaFPField; private static AddressField osThreadField; - // Field from OSThread + // Fields from OSThread private static CIntegerField osThreadThreadIDField; + private static CIntegerField osThreadUniqueThreadIDField; // This is currently unneeded but is being kept in case we change // the currentFrameGuess algorithm @@ -61,7 +64,8 @@ lastJavaFPField = anchorType.getAddressField("_last_Java_fp"); Type osThreadType = db.lookupType("OSThread"); - osThreadThreadIDField = osThreadType.getCIntegerField("_thread_id"); + osThreadThreadIDField = osThreadType.getCIntegerField("_thread_id"); + osThreadUniqueThreadIDField = osThreadType.getCIntegerField("_unique_thread_id"); } public Address getLastJavaFP(Address addr) { @@ -125,8 +129,9 @@ Address osThreadAddr = osThreadField.getValue(addr); // Get the address of the _thread_id from the OSThread Address threadIdAddr = osThreadAddr.addOffsetTo(osThreadThreadIDField.getOffset()); + Address uniqueThreadIdAddr = osThreadAddr.addOffsetTo(osThreadUniqueThreadIDField.getOffset()); - JVMDebugger debugger = VM.getVM().getDebugger(); - return debugger.getThreadForIdentifierAddress(threadIdAddr); + BsdDebuggerLocal debugger = (BsdDebuggerLocal) VM.getVM().getDebugger(); + return debugger.getThreadForIdentifierAddress(threadIdAddr, uniqueThreadIdAddr); } } diff -r a413bcd552a4 -r 5fc51c1ecdeb agent/src/share/classes/sun/jvm/hotspot/runtime/win32_amd64/Win32AMD64JavaThreadPDAccess.java --- a/agent/src/share/classes/sun/jvm/hotspot/runtime/win32_amd64/Win32AMD64JavaThreadPDAccess.java Tue Mar 05 21:58:51 2013 +0100 +++ b/agent/src/share/classes/sun/jvm/hotspot/runtime/win32_amd64/Win32AMD64JavaThreadPDAccess.java Tue Mar 05 23:44:54 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -43,7 +43,7 @@ private static AddressField osThreadField; // Field from OSThread - private static Field osThreadThreadHandleField; + private static Field osThreadThreadIdField; // This is currently unneeded but is being kept in case we change // the currentFrameGuess algorithm @@ -64,7 +64,7 @@ osThreadField = type.getAddressField("_osthread"); type = db.lookupType("OSThread"); - osThreadThreadHandleField = type.getField("_thread_handle"); + osThreadThreadIdField = type.getField("_thread_id"); } public Address getLastJavaFP(Address addr) { @@ -128,10 +128,10 @@ // Fetch the OSThread (for now and for simplicity, not making a // separate "OSThread" class in this package) Address osThreadAddr = osThreadField.getValue(addr); - // Get the address of the HANDLE within the OSThread - Address threadHandleAddr = - osThreadAddr.addOffsetTo(osThreadThreadHandleField.getOffset()); + // Get the address of the thread_id within the OSThread + Address threadIdAddr = + osThreadAddr.addOffsetTo(osThreadThreadIdField.getOffset()); JVMDebugger debugger = VM.getVM().getDebugger(); - return debugger.getThreadForIdentifierAddress(threadHandleAddr); + return debugger.getThreadForIdentifierAddress(threadIdAddr); } } diff -r a413bcd552a4 -r 5fc51c1ecdeb agent/src/share/classes/sun/jvm/hotspot/runtime/win32_x86/Win32X86JavaThreadPDAccess.java --- a/agent/src/share/classes/sun/jvm/hotspot/runtime/win32_x86/Win32X86JavaThreadPDAccess.java Tue Mar 05 21:58:51 2013 +0100 +++ b/agent/src/share/classes/sun/jvm/hotspot/runtime/win32_x86/Win32X86JavaThreadPDAccess.java Tue Mar 05 23:44:54 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -42,7 +42,7 @@ private static AddressField osThreadField; // Field from OSThread - private static Field osThreadThreadHandleField; + private static Field osThreadThreadIdField; // This is currently unneeded but is being kept in case we change // the currentFrameGuess algorithm @@ -63,7 +63,7 @@ osThreadField = type.getAddressField("_osthread"); type = db.lookupType("OSThread"); - osThreadThreadHandleField = type.getField("_thread_handle"); + osThreadThreadIdField = type.getField("_thread_id"); } public Address getLastJavaFP(Address addr) { @@ -127,10 +127,10 @@ // Fetch the OSThread (for now and for simplicity, not making a // separate "OSThread" class in this package) Address osThreadAddr = osThreadField.getValue(addr); - // Get the address of the HANDLE within the OSThread - Address threadHandleAddr = - osThreadAddr.addOffsetTo(osThreadThreadHandleField.getOffset()); + // Get the address of the thread_id within the OSThread + Address threadIdAddr = + osThreadAddr.addOffsetTo(osThreadThreadIdField.getOffset()); JVMDebugger debugger = VM.getVM().getDebugger(); - return debugger.getThreadForIdentifierAddress(threadHandleAddr); + return debugger.getThreadForIdentifierAddress(threadIdAddr); } } diff -r a413bcd552a4 -r 5fc51c1ecdeb agent/src/share/classes/sun/jvm/hotspot/tools/ClassLoaderStats.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/agent/src/share/classes/sun/jvm/hotspot/tools/ClassLoaderStats.java Tue Mar 05 23:44:54 2013 +0100 @@ -0,0 +1,277 @@ +/* + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package sun.jvm.hotspot.tools; + +import java.io.*; +import java.util.*; + +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.memory.*; +import sun.jvm.hotspot.oops.*; +import sun.jvm.hotspot.runtime.*; +import sun.jvm.hotspot.tools.*; +import sun.jvm.hotspot.utilities.*; + +/** + A command line tool to print class loader statistics. +*/ + +public class ClassLoaderStats extends Tool { + boolean verbose = true; + + public static void main(String[] args) { + ClassLoaderStats cls = new ClassLoaderStats(); + cls.start(args); + cls.stop(); + } + + private static class ClassData { + Klass klass; + long size; + + ClassData(Klass klass, long size) { + this.klass = klass; this.size = size; + } + } + + private static class LoaderData { + long numClasses; + long classSize; + List classDetail = new ArrayList(); // List + } + + public void run() { + printClassLoaderStatistics(); + } + + private void printClassLoaderStatistics() { + final PrintStream out = System.out; + final PrintStream err = System.err; + final Map loaderMap = new HashMap(); + // loader data for bootstrap class loader + final LoaderData bootstrapLoaderData = new LoaderData(); + if (verbose) { + err.print("finding class loader instances .."); + } + + VM vm = VM.getVM(); + ObjectHeap heap = vm.getObjectHeap(); + Klass classLoaderKlass = vm.getSystemDictionary().getClassLoaderKlass(); + try { + heap.iterateObjectsOfKlass(new DefaultHeapVisitor() { + public boolean doObj(Oop oop) { + loaderMap.put(oop, new LoaderData()); + return false; + } + }, classLoaderKlass); + } catch (Exception se) { + se.printStackTrace(); + } + + if (verbose) { + err.println("done."); + err.print("computing per loader stat .."); + } + + SystemDictionary dict = VM.getVM().getSystemDictionary(); + dict.classesDo(new SystemDictionary.ClassAndLoaderVisitor() { + public void visit(Klass k, Oop loader) { + if (! (k instanceof InstanceKlass)) { + return; + } + LoaderData ld = (loader != null) ? (LoaderData)loaderMap.get(loader) + : bootstrapLoaderData; + if (ld != null) { + ld.numClasses++; + long size = computeSize((InstanceKlass)k); + ld.classDetail.add(new ClassData(k, size)); + ld.classSize += size; + } + } + }); + + if (verbose) { + err.println("done."); + err.print("please wait.. computing liveness"); + } + + // compute reverse pointer analysis (takes long time for larger app) + ReversePtrsAnalysis analysis = new ReversePtrsAnalysis(); + + if (verbose) { + analysis.setHeapProgressThunk(new HeapProgressThunk() { + public void heapIterationFractionUpdate(double fractionOfHeapVisited) { + err.print('.'); + } + // This will be called after the iteration is complete + public void heapIterationComplete() { + err.println("done."); + } + }); + } + + try { + analysis.run(); + } catch (Exception e) { + // e.printStackTrace(); + if (verbose) + err.println("liveness analysis may be inaccurate ..."); + } + ReversePtrs liveness = VM.getVM().getRevPtrs(); + + out.println("class_loader\tclasses\tbytes\tparent_loader\talive?\ttype"); + out.println(); + + long numClassLoaders = 1L; + long totalNumClasses = bootstrapLoaderData.numClasses; + long totalClassSize = bootstrapLoaderData.classSize; + long numAliveLoaders = 1L; + long numDeadLoaders = 0L; + + // print bootstrap loader details + out.print(""); + out.print('\t'); + out.print(bootstrapLoaderData.numClasses); + out.print('\t'); + out.print(bootstrapLoaderData.classSize); + out.print('\t'); + out.print(" null "); + out.print('\t'); + // bootstrap loader is always alive + out.print("live"); + out.print('\t'); + out.println(""); + + for (Iterator keyItr = loaderMap.keySet().iterator(); keyItr.hasNext();) { + Oop loader = (Oop) keyItr.next(); + LoaderData data = (LoaderData) loaderMap.get(loader); + numClassLoaders ++; + totalNumClasses += data.numClasses; + totalClassSize += data.classSize; + + out.print(loader.getHandle()); + out.print('\t'); + out.print(data.numClasses); + out.print('\t'); + out.print(data.classSize); + out.print('\t'); + + class ParentFinder extends DefaultOopVisitor { + public void doOop(OopField field, boolean isVMField) { + if (field.getID().getName().equals("parent")) { + parent = field.getValue(getObj()); + } + } + private Oop parent = null; + public Oop getParent() { return parent; } + } + + ParentFinder parentFinder = new ParentFinder(); + loader.iterate(parentFinder, false); + Oop parent = parentFinder.getParent(); + out.print((parent != null)? parent.getHandle().toString() : " null "); + out.print('\t'); + boolean alive = (liveness != null) ? (liveness.get(loader) != null) : true; + out.print(alive? "live" : "dead"); + if (alive) numAliveLoaders++; else numDeadLoaders++; + out.print('\t'); + Klass loaderKlass = loader.getKlass(); + if (loaderKlass != null) { + out.print(loaderKlass.getName().asString()); + out.print('@'); + out.print(loader.getKlass().getAddress()); + } else { + out.print(" null! "); + } + out.println(); + } + + out.println(); + // summary line + out.print("total = "); + out.print(numClassLoaders); + out.print('\t'); + out.print(totalNumClasses); + out.print('\t'); + out.print(totalClassSize); + out.print('\t'); + out.print(" N/A "); + out.print('\t'); + out.print("alive="); + out.print(numAliveLoaders); + out.print(", dead="); + out.print(numDeadLoaders); + out.print('\t'); + out.print(" N/A "); + out.println(); + } + + private static long objectSize(Oop oop) { + return oop == null ? 0L : oop.getObjectSize(); + } + + // Don't count the shared empty arrays + private static long arraySize(GenericArray arr) { + return arr.getLength() != 0L ? arr.getSize() : 0L; + } + + private long computeSize(InstanceKlass k) { + long size = 0L; + // the InstanceKlass object itself + size += k.getSize(); + + // Constant pool + ConstantPool cp = k.getConstants(); + size += cp.getSize(); + if (cp.getCache() != null) { + size += cp.getCache().getSize(); + } + size += arraySize(cp.getTags()); + + // Interfaces + size += arraySize(k.getLocalInterfaces()); + size += arraySize(k.getTransitiveInterfaces()); + + // Inner classes + size += arraySize(k.getInnerClasses()); + + // Fields + size += arraySize(k.getFields()); + + // Methods + MethodArray methods = k.getMethods(); + int nmethods = (int) methods.getLength(); + if (nmethods != 0L) { + size += methods.getSize(); + for (int i = 0; i < nmethods; ++i) { + Method m = methods.at(i); + size += m.getSize(); + size += m.getConstMethod().getSize(); + } + } + + return size; + } +} diff -r a413bcd552a4 -r 5fc51c1ecdeb agent/src/share/classes/sun/jvm/hotspot/tools/HeapSummary.java --- a/agent/src/share/classes/sun/jvm/hotspot/tools/HeapSummary.java Tue Mar 05 21:58:51 2013 +0100 +++ b/agent/src/share/classes/sun/jvm/hotspot/tools/HeapSummary.java Tue Mar 05 23:44:54 2013 +0100 @@ -57,17 +57,18 @@ printGCAlgorithm(flagMap); System.out.println(); System.out.println("Heap Configuration:"); - printValue("MinHeapFreeRatio = ", getFlagValue("MinHeapFreeRatio", flagMap)); - printValue("MaxHeapFreeRatio = ", getFlagValue("MaxHeapFreeRatio", flagMap)); - printValMB("MaxHeapSize = ", getFlagValue("MaxHeapSize", flagMap)); - printValMB("NewSize = ", getFlagValue("NewSize", flagMap)); - printValMB("MaxNewSize = ", getFlagValue("MaxNewSize", flagMap)); - printValMB("OldSize = ", getFlagValue("OldSize", flagMap)); - printValue("NewRatio = ", getFlagValue("NewRatio", flagMap)); - printValue("SurvivorRatio = ", getFlagValue("SurvivorRatio", flagMap)); - printValMB("MetaspaceSize = ", getFlagValue("MetaspaceSize", flagMap)); - printValMB("MaxMetaspaceSize = ", getFlagValue("MaxMetaspaceSize", flagMap)); - printValMB("G1HeapRegionSize = ", HeapRegion.grainBytes()); + printValue("MinHeapFreeRatio = ", getFlagValue("MinHeapFreeRatio", flagMap)); + printValue("MaxHeapFreeRatio = ", getFlagValue("MaxHeapFreeRatio", flagMap)); + printValMB("MaxHeapSize = ", getFlagValue("MaxHeapSize", flagMap)); + printValMB("NewSize = ", getFlagValue("NewSize", flagMap)); + printValMB("MaxNewSize = ", getFlagValue("MaxNewSize", flagMap)); + printValMB("OldSize = ", getFlagValue("OldSize", flagMap)); + printValue("NewRatio = ", getFlagValue("NewRatio", flagMap)); + printValue("SurvivorRatio = ", getFlagValue("SurvivorRatio", flagMap)); + printValMB("MetaspaceSize = ", getFlagValue("MetaspaceSize", flagMap)); + printValMB("ClassMetaspaceSize = ", getFlagValue("ClassMetaspaceSize", flagMap)); + printValMB("MaxMetaspaceSize = ", getFlagValue("MaxMetaspaceSize", flagMap)); + printValMB("G1HeapRegionSize = ", HeapRegion.grainBytes()); System.out.println(); System.out.println("Heap Usage:"); diff -r a413bcd552a4 -r 5fc51c1ecdeb agent/src/share/classes/sun/jvm/hotspot/tools/JMap.java --- a/agent/src/share/classes/sun/jvm/hotspot/tools/JMap.java Tue Mar 05 21:58:51 2013 +0100 +++ b/agent/src/share/classes/sun/jvm/hotspot/tools/JMap.java Tue Mar 05 23:44:54 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -45,7 +45,7 @@ } protected String getCommandFlags() { - return "-heap|-heap:format=b|-histo|-permstat|-finalizerinfo"; + return "-heap|-heap:format=b|-histo|-clstats|-finalizerinfo"; } protected void printFlagsUsage() { @@ -53,14 +53,14 @@ System.out.println(" -heap\tto print java heap summary"); System.out.println(" -heap:format=b\tto dump java heap in hprof binary format"); System.out.println(" -histo\tto print histogram of java object heap"); - System.out.println(" -permstat\tto print permanent generation statistics"); + System.out.println(" -clstats\tto print class loader statistics"); System.out.println(" -finalizerinfo\tto print information on objects awaiting finalization"); super.printFlagsUsage(); } public static final int MODE_HEAP_SUMMARY = 0; public static final int MODE_HISTOGRAM = 1; - public static final int MODE_PERMSTAT = 2; + public static final int MODE_CLSTATS = 2; public static final int MODE_PMAP = 3; public static final int MODE_HEAP_GRAPH_HPROF_BIN = 4; public static final int MODE_HEAP_GRAPH_GXL = 5; @@ -78,8 +78,8 @@ tool = new ObjectHistogram(); break; - case MODE_PERMSTAT: - tool = new PermStat(); + case MODE_CLSTATS: + tool = new ClassLoaderStats(); break; case MODE_PMAP: @@ -118,7 +118,9 @@ } else if (modeFlag.equals("-histo")) { mode = MODE_HISTOGRAM; } else if (modeFlag.equals("-permstat")) { - mode = MODE_PERMSTAT; + mode = MODE_CLSTATS; + } else if (modeFlag.equals("-clstats")) { + mode = MODE_CLSTATS; } else if (modeFlag.equals("-finalizerinfo")) { mode = MODE_FINALIZERINFO; } else { diff -r a413bcd552a4 -r 5fc51c1ecdeb agent/src/share/classes/sun/jvm/hotspot/tools/PMap.java --- a/agent/src/share/classes/sun/jvm/hotspot/tools/PMap.java Tue Mar 05 21:58:51 2013 +0100 +++ b/agent/src/share/classes/sun/jvm/hotspot/tools/PMap.java Tue Mar 05 23:44:54 2013 +0100 @@ -58,10 +58,6 @@ } } - protected boolean requiresVM() { - return false; - } - public static void main(String[] args) throws Exception { PMap t = new PMap(); t.start(args); diff -r a413bcd552a4 -r 5fc51c1ecdeb agent/src/share/classes/sun/jvm/hotspot/tools/PStack.java --- a/agent/src/share/classes/sun/jvm/hotspot/tools/PStack.java Tue Mar 05 21:58:51 2013 +0100 +++ b/agent/src/share/classes/sun/jvm/hotspot/tools/PStack.java Tue Mar 05 23:44:54 2013 +0100 @@ -50,29 +50,23 @@ public void run(PrintStream out) { Debugger dbg = getAgent().getDebugger(); - run(out, dbg, getAgent().isJavaMode()); + run(out, dbg); } public void run(PrintStream out, Debugger dbg) { - run(out, dbg, true); - } - - private void run(PrintStream out, Debugger dbg, final boolean isJava) { CDebugger cdbg = dbg.getCDebugger(); if (cdbg != null) { ConcurrentLocksPrinter concLocksPrinter = null; - if (isJava) { - // compute and cache java Vframes. - initJFrameCache(); - if (concurrentLocks) { - concLocksPrinter = new ConcurrentLocksPrinter(); - } - // print Java level deadlocks - try { - DeadlockDetector.print(out); - } catch (Exception exp) { - out.println("can't print deadlock information: " + exp.getMessage()); - } + // compute and cache java Vframes. + initJFrameCache(); + if (concurrentLocks) { + concLocksPrinter = new ConcurrentLocksPrinter(); + } + // print Java level deadlocks + try { + DeadlockDetector.print(out); + } catch (Exception exp) { + out.println("can't print deadlock information: " + exp.getMessage()); } List l = cdbg.getThreadList(); @@ -100,63 +94,59 @@ } out.println(); } else { - if (isJava) { - // look for one or more java frames - String[] names = null; - // check interpreter frame - Interpreter interp = VM.getVM().getInterpreter(); - if (interp.contains(pc)) { - names = getJavaNames(th, f.localVariableBase()); - // print codelet name if we can't determine method - if (names == null || names.length == 0) { - out.print(" "); - InterpreterCodelet ic = interp.getCodeletContaining(pc); - if (ic != null) { - String desc = ic.getDescription(); - if (desc != null) out.print(desc); - } - out.println(); - } - } else { - // look for known code blobs - CodeCache c = VM.getVM().getCodeCache(); - if (c.contains(pc)) { - CodeBlob cb = c.findBlobUnsafe(pc); - if (cb.isNMethod()) { - names = getJavaNames(th, f.localVariableBase()); - // just print compiled code, if can't determine method - if (names == null || names.length == 0) { - out.println(""); - } - } else if (cb.isBufferBlob()) { - out.println(""); - } else if (cb.isRuntimeStub()) { - out.println(""); - } else if (cb.isDeoptimizationStub()) { - out.println(""); - } else if (cb.isUncommonTrapStub()) { - out.println(""); - } else if (cb.isExceptionStub()) { - out.println(""); - } else if (cb.isSafepointStub()) { - out.println(""); - } else { - out.println(""); - } - } else { - printUnknown(out); - } - } - // print java frames, if any - if (names != null && names.length != 0) { - // print java frame(s) - for (int i = 0; i < names.length; i++) { - out.println(names[i]); - } - } - } else { - printUnknown(out); - } + // look for one or more java frames + String[] names = null; + // check interpreter frame + Interpreter interp = VM.getVM().getInterpreter(); + if (interp.contains(pc)) { + names = getJavaNames(th, f.localVariableBase()); + // print codelet name if we can't determine method + if (names == null || names.length == 0) { + out.print(" "); + InterpreterCodelet ic = interp.getCodeletContaining(pc); + if (ic != null) { + String desc = ic.getDescription(); + if (desc != null) out.print(desc); + } + out.println(); + } + } else { + // look for known code blobs + CodeCache c = VM.getVM().getCodeCache(); + if (c.contains(pc)) { + CodeBlob cb = c.findBlobUnsafe(pc); + if (cb.isNMethod()) { + names = getJavaNames(th, f.localVariableBase()); + // just print compiled code, if can't determine method + if (names == null || names.length == 0) { + out.println(""); + } + } else if (cb.isBufferBlob()) { + out.println(""); + } else if (cb.isRuntimeStub()) { + out.println(""); + } else if (cb.isDeoptimizationStub()) { + out.println(""); + } else if (cb.isUncommonTrapStub()) { + out.println(""); + } else if (cb.isExceptionStub()) { + out.println(""); + } else if (cb.isSafepointStub()) { + out.println(""); + } else { + out.println(""); + } + } else { + printUnknown(out); + } + } + // print java frames, if any + if (names != null && names.length != 0) { + // print java frame(s) + for (int i = 0; i < names.length; i++) { + out.println(names[i]); + } + } } f = f.sender(th); } @@ -164,7 +154,7 @@ exp.printStackTrace(); // continue, may be we can do a better job for other threads } - if (isJava && concurrentLocks) { + if (concurrentLocks) { JavaThread jthread = (JavaThread) proxyToThread.get(th); if (jthread != null) { concLocksPrinter.print(jthread, out); @@ -180,10 +170,6 @@ } } - protected boolean requiresVM() { - return false; - } - public static void main(String[] args) throws Exception { PStack t = new PStack(); t.start(args); diff -r a413bcd552a4 -r 5fc51c1ecdeb agent/src/share/classes/sun/jvm/hotspot/tools/PermStat.java --- a/agent/src/share/classes/sun/jvm/hotspot/tools/PermStat.java Tue Mar 05 21:58:51 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,277 +0,0 @@ -/* - * Copyright (c) 2003, 2012, 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 sun.jvm.hotspot.tools; - -import java.io.*; -import java.util.*; - -import sun.jvm.hotspot.debugger.*; -import sun.jvm.hotspot.memory.*; -import sun.jvm.hotspot.oops.*; -import sun.jvm.hotspot.runtime.*; -import sun.jvm.hotspot.tools.*; -import sun.jvm.hotspot.utilities.*; - -/** - A command line tool to print perm. generation statistics. -*/ - -public class PermStat extends Tool { - boolean verbose = true; - - public static void main(String[] args) { - PermStat ps = new PermStat(); - ps.start(args); - ps.stop(); - } - - private static class ClassData { - Klass klass; - long size; - - ClassData(Klass klass, long size) { - this.klass = klass; this.size = size; - } - } - - private static class LoaderData { - long numClasses; - long classSize; - List classDetail = new ArrayList(); // List - } - - public void run() { - printClassLoaderStatistics(); - } - - private void printClassLoaderStatistics() { - final PrintStream out = System.out; - final PrintStream err = System.err; - final Map loaderMap = new HashMap(); - // loader data for bootstrap class loader - final LoaderData bootstrapLoaderData = new LoaderData(); - if (verbose) { - err.print("finding class loader instances .."); - } - - VM vm = VM.getVM(); - ObjectHeap heap = vm.getObjectHeap(); - Klass classLoaderKlass = vm.getSystemDictionary().getClassLoaderKlass(); - try { - heap.iterateObjectsOfKlass(new DefaultHeapVisitor() { - public boolean doObj(Oop oop) { - loaderMap.put(oop, new LoaderData()); - return false; - } - }, classLoaderKlass); - } catch (Exception se) { - se.printStackTrace(); - } - - if (verbose) { - err.println("done."); - err.print("computing per loader stat .."); - } - - SystemDictionary dict = VM.getVM().getSystemDictionary(); - dict.classesDo(new SystemDictionary.ClassAndLoaderVisitor() { - public void visit(Klass k, Oop loader) { - if (! (k instanceof InstanceKlass)) { - return; - } - LoaderData ld = (loader != null) ? (LoaderData)loaderMap.get(loader) - : bootstrapLoaderData; - if (ld != null) { - ld.numClasses++; - long size = computeSize((InstanceKlass)k); - ld.classDetail.add(new ClassData(k, size)); - ld.classSize += size; - } - } - }); - - if (verbose) { - err.println("done."); - err.print("please wait.. computing liveness"); - } - - // compute reverse pointer analysis (takes long time for larger app) - ReversePtrsAnalysis analysis = new ReversePtrsAnalysis(); - - if (verbose) { - analysis.setHeapProgressThunk(new HeapProgressThunk() { - public void heapIterationFractionUpdate(double fractionOfHeapVisited) { - err.print('.'); - } - // This will be called after the iteration is complete - public void heapIterationComplete() { - err.println("done."); - } - }); - } - - try { - analysis.run(); - } catch (Exception e) { - // e.printStackTrace(); - if (verbose) - err.println("liveness analysis may be inaccurate ..."); - } - ReversePtrs liveness = VM.getVM().getRevPtrs(); - - out.println("class_loader\tclasses\tbytes\tparent_loader\talive?\ttype"); - out.println(); - - long numClassLoaders = 1L; - long totalNumClasses = bootstrapLoaderData.numClasses; - long totalClassSize = bootstrapLoaderData.classSize; - long numAliveLoaders = 1L; - long numDeadLoaders = 0L; - - // print bootstrap loader details - out.print(""); - out.print('\t'); - out.print(bootstrapLoaderData.numClasses); - out.print('\t'); - out.print(bootstrapLoaderData.classSize); - out.print('\t'); - out.print(" null "); - out.print('\t'); - // bootstrap loader is always alive - out.print("live"); - out.print('\t'); - out.println(""); - - for (Iterator keyItr = loaderMap.keySet().iterator(); keyItr.hasNext();) { - Oop loader = (Oop) keyItr.next(); - LoaderData data = (LoaderData) loaderMap.get(loader); - numClassLoaders ++; - totalNumClasses += data.numClasses; - totalClassSize += data.classSize; - - out.print(loader.getHandle()); - out.print('\t'); - out.print(data.numClasses); - out.print('\t'); - out.print(data.classSize); - out.print('\t'); - - class ParentFinder extends DefaultOopVisitor { - public void doOop(OopField field, boolean isVMField) { - if (field.getID().getName().equals("parent")) { - parent = field.getValue(getObj()); - } - } - private Oop parent = null; - public Oop getParent() { return parent; } - } - - ParentFinder parentFinder = new ParentFinder(); - loader.iterate(parentFinder, false); - Oop parent = parentFinder.getParent(); - out.print((parent != null)? parent.getHandle().toString() : " null "); - out.print('\t'); - boolean alive = (liveness != null) ? (liveness.get(loader) != null) : true; - out.print(alive? "live" : "dead"); - if (alive) numAliveLoaders++; else numDeadLoaders++; - out.print('\t'); - Klass loaderKlass = loader.getKlass(); - if (loaderKlass != null) { - out.print(loaderKlass.getName().asString()); - out.print('@'); - out.print(loader.getKlass().getAddress()); - } else { - out.print(" null! "); - } - out.println(); - } - - out.println(); - // summary line - out.print("total = "); - out.print(numClassLoaders); - out.print('\t'); - out.print(totalNumClasses); - out.print('\t'); - out.print(totalClassSize); - out.print('\t'); - out.print(" N/A "); - out.print('\t'); - out.print("alive="); - out.print(numAliveLoaders); - out.print(", dead="); - out.print(numDeadLoaders); - out.print('\t'); - out.print(" N/A "); - out.println(); - } - - private static long objectSize(Oop oop) { - return oop == null ? 0L : oop.getObjectSize(); - } - - // Don't count the shared empty arrays - private static long arraySize(GenericArray arr) { - return arr.getLength() != 0L ? arr.getSize() : 0L; - } - - private long computeSize(InstanceKlass k) { - long size = 0L; - // the InstanceKlass object itself - size += k.getSize(); - - // Constant pool - ConstantPool cp = k.getConstants(); - size += cp.getSize(); - if (cp.getCache() != null) { - size += cp.getCache().getSize(); - } - size += arraySize(cp.getTags()); - - // Interfaces - size += arraySize(k.getLocalInterfaces()); - size += arraySize(k.getTransitiveInterfaces()); - - // Inner classes - size += arraySize(k.getInnerClasses()); - - // Fields - size += arraySize(k.getFields()); - - // Methods - MethodArray methods = k.getMethods(); - int nmethods = (int) methods.getLength(); - if (nmethods != 0L) { - size += methods.getSize(); - for (int i = 0; i < nmethods; ++i) { - Method m = methods.at(i); - size += m.getSize(); - size += m.getConstMethod().getSize(); - } - } - - return size; - } -} diff -r a413bcd552a4 -r 5fc51c1ecdeb agent/src/share/classes/sun/jvm/hotspot/tools/Tool.java --- a/agent/src/share/classes/sun/jvm/hotspot/tools/Tool.java Tue Mar 05 21:58:51 2013 +0100 +++ b/agent/src/share/classes/sun/jvm/hotspot/tools/Tool.java Tue Mar 05 23:44:54 2013 +0100 @@ -27,7 +27,6 @@ import java.io.PrintStream; import java.util.Hashtable; import sun.jvm.hotspot.*; -import sun.jvm.hotspot.bugspot.*; import sun.jvm.hotspot.runtime.*; import sun.jvm.hotspot.debugger.*; @@ -35,7 +34,7 @@ // override run & code main as shown below. public abstract class Tool implements Runnable { - private BugSpotAgent agent; + private HotSpotAgent agent; private int debugeeType; // debugeeType is one of constants below @@ -51,12 +50,7 @@ return true; } - // whether this tool requires debuggee to be java process or core? - protected boolean requiresVM() { - return true; - } - - protected void setAgent(BugSpotAgent a) { + protected void setAgent(HotSpotAgent a) { agent = a; } @@ -64,7 +58,7 @@ debugeeType = dt; } - protected BugSpotAgent getAgent() { + protected HotSpotAgent getAgent() { return agent; } @@ -155,7 +149,7 @@ usage(); } - agent = new BugSpotAgent(); + agent = new HotSpotAgent(); try { switch (debugeeType) { case DEBUGEE_PID: @@ -198,33 +192,24 @@ err.println("Debugger attached successfully."); - boolean isJava = agent.isJavaMode(); - if (isJava) { - VM vm = VM.getVM(); - if (vm.isCore()) { - err.println("Core build detected."); - } else if (vm.isClientCompiler()) { - err.println("Client compiler detected."); - } else if (vm.isServerCompiler()) { - err.println("Server compiler detected."); - } else { - throw new RuntimeException("Fatal error: " + - "should have been able to detect core/C1/C2 build"); - } + VM vm = VM.getVM(); + if (vm.isCore()) { + err.println("Core build detected."); + } else if (vm.isClientCompiler()) { + err.println("Client compiler detected."); + } else if (vm.isServerCompiler()) { + err.println("Server compiler detected."); + } else { + throw new RuntimeException("Fatal error: " + + "should have been able to detect core/C1/C2 build"); + } - String version = vm.getVMRelease(); - if (version != null) { - err.print("JVM version is "); - err.println(version); - } + String version = vm.getVMRelease(); + if (version != null) { + err.print("JVM version is "); + err.println(version); + } - run(); - } else { // not a java process or core - if (requiresVM()) { - err.println(getName() + " requires a java VM process/core!"); - } else { - run(); - } - } + run(); } } diff -r a413bcd552a4 -r 5fc51c1ecdeb agent/src/share/classes/sun/jvm/hotspot/ui/SAPanel.java --- a/agent/src/share/classes/sun/jvm/hotspot/ui/SAPanel.java Tue Mar 05 21:58:51 2013 +0100 +++ b/agent/src/share/classes/sun/jvm/hotspot/ui/SAPanel.java Tue Mar 05 23:44:54 2013 +0100 @@ -50,7 +50,7 @@ /** * This base class encapsulates many of the events that are fired from * the various panels in this directory so they can easily be plugged - * in to different containing frameworks (HSDB, BugSpot). + * in to different containing frameworks (HSDB). */ public class SAPanel extends JPanel { protected List listeners = new ArrayList(); diff -r a413bcd552a4 -r 5fc51c1ecdeb agent/src/share/classes/sun/jvm/hotspot/utilities/ConstantTag.java --- a/agent/src/share/classes/sun/jvm/hotspot/utilities/ConstantTag.java Tue Mar 05 21:58:51 2013 +0100 +++ b/agent/src/share/classes/sun/jvm/hotspot/utilities/ConstantTag.java Tue Mar 05 23:44:54 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -51,7 +51,6 @@ private static final int JVM_CONSTANT_UnresolvedClassInError = 103; // Resolution failed private static final int JVM_CONSTANT_MethodHandleInError = 104; // Error tag due to resolution error private static final int JVM_CONSTANT_MethodTypeInError = 105; // Error tag due to resolution error - private static final int JVM_CONSTANT_Object = 106; // Required for BoundMethodHandle arguments. // JVM_CONSTANT_MethodHandle subtypes //FIXME: connect these to data structure private static int JVM_REF_getField = 1; @@ -96,8 +95,6 @@ public boolean isKlassIndex() { return tag == JVM_CONSTANT_ClassIndex; } public boolean isStringIndex() { return tag == JVM_CONSTANT_StringIndex; } - public boolean isObject() { return tag == JVM_CONSTANT_Object; } - public boolean isKlassReference() { return isKlassIndex() || isUnresolvedKlass(); } public boolean isFieldOrMethod() { return isField() || isMethod() || isInterfaceMethod(); } public boolean isSymbol() { return isUtf8(); } @@ -123,7 +120,6 @@ case JVM_CONSTANT_StringIndex : case JVM_CONSTANT_MethodHandle : case JVM_CONSTANT_MethodType : - case JVM_CONSTANT_Object : return BasicType.T_OBJECT; default: throw new InternalError("unexpected tag: " + tag); diff -r a413bcd552a4 -r 5fc51c1ecdeb agent/src/share/classes/sun/jvm/hotspot/utilities/soql/sa.js --- a/agent/src/share/classes/sun/jvm/hotspot/utilities/soql/sa.js Tue Mar 05 21:58:51 2013 +0100 +++ b/agent/src/share/classes/sun/jvm/hotspot/utilities/soql/sa.js Tue Mar 05 23:44:54 2013 +0100 @@ -31,7 +31,6 @@ sapkg.hotspot = Packages.sun.jvm.hotspot; sapkg.asm = sapkg.hotspot.asm; -sapkg.bugspot = sapkg.hotspot.bugspot; sapkg.c1 = sapkg.hotspot.c1; sapkg.code = sapkg.hotspot.code; sapkg.compiler = sapkg.hotspot.compiler; @@ -40,7 +39,6 @@ // sapkg.debugger = sapkg.hotspot.debugger; sapkg.interpreter = sapkg.hotspot.interpreter; -sapkg.livejvm = sapkg.hotspot.livejvm; sapkg.jdi = sapkg.hotspot.jdi; sapkg.memory = sapkg.hotspot.memory; sapkg.oops = sapkg.hotspot.oops; diff -r a413bcd552a4 -r 5fc51c1ecdeb agent/src/share/native/jvmdi/sa.cpp --- a/agent/src/share/native/jvmdi/sa.cpp Tue Mar 05 21:58:51 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,601 +0,0 @@ -/* - * Copyright (c) 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. - * - * 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 -#include -#include -#include -#include "sa.hpp" -#include "jni.h" -#include "jvmdi.h" - -#ifndef WIN32 - #include -#else - typedef int int32_t; -#endif - -#ifdef WIN32 - #include - #define YIELD() Sleep(0) - #define SLEEP() Sleep(10) - #define vsnprintf _vsnprintf -#else - Error: please port YIELD() and SLEEP() macros to your platform -#endif - -using namespace std; - -////////////////////////////////////////////////////////////////////// -// // -// Exported "interface" for Java language-level interaction between // -// the SA and the VM. Note that the SA knows about the layout of // -// certain VM data structures and that knowledge is taken advantage // -// of in this code, although this interfaces with the VM via JVMDI. // -// // -////////////////////////////////////////////////////////////////////// - -extern "C" { - ///////////////////////////////////// - // // - // Events sent by the VM to the SA // - // // - ///////////////////////////////////// - - // Set by the SA when it attaches. Indicates that events should be - // posted via these exported variables, and that the VM should wait - // for those events to be acknowledged by the SA (via its setting - // saEventPending to 0). - JNIEXPORT volatile int32_t saAttached = 0; - - // Set to nonzero value by the VM when an event has been posted; set - // back to 0 by the SA when it has processed that event. - JNIEXPORT volatile int32_t saEventPending = 0; - - // Kind of the event (from jvmdi.h) - JNIEXPORT volatile int32_t saEventKind = 0; - - // - // Exception events - // - JNIEXPORT jthread saExceptionThread; - JNIEXPORT jclass saExceptionClass; - JNIEXPORT jmethodID saExceptionMethod; - JNIEXPORT int32_t saExceptionLocation; - JNIEXPORT jobject saExceptionException; - JNIEXPORT jclass saExceptionCatchClass; - JNIEXPORT jmethodID saExceptionCatchMethod; - JNIEXPORT int32_t saExceptionCatchLocation; - - // - // Breakpoint events - // - JNIEXPORT jthread saBreakpointThread; - JNIEXPORT jclass saBreakpointClass; - JNIEXPORT jmethodID saBreakpointMethod; - JNIEXPORT jlocation saBreakpointLocation; - - /////////////////////////////////////// - // // - // Commands sent by the SA to the VM // - // // - /////////////////////////////////////// - - extern JNIEXPORT const int32_t SA_CMD_SUSPEND_ALL = 0; - extern JNIEXPORT const int32_t SA_CMD_RESUME_ALL = 1; - extern JNIEXPORT const int32_t SA_CMD_TOGGLE_BREAKPOINT = 2; - extern JNIEXPORT const int32_t SA_CMD_BUF_SIZE = 1024; - - // SA sets this to a nonzero value when it is requesting a command - // to be processed; VM sets it back to 0 when the command has been - // executed - JNIEXPORT volatile int32_t saCmdPending = 0; - - // SA sets this to one of the manifest constants above to indicate - // the kind of command to be executed - JNIEXPORT volatile int32_t saCmdType = 0; - - // VM sets this to 0 if the last command succeeded or a nonzero - // value if it failed - JNIEXPORT volatile int32_t saCmdResult = 0; - - // If last command failed, this buffer will contain a descriptive - // error message - JNIEXPORT char saCmdResultErrMsg[SA_CMD_BUF_SIZE]; - - // - // Toggling of breakpoint command arguments. - // - // Originally there were separate set/clear breakpoint commands - // taking a class name, method name and signature, and the iteration - // through the debug information was done in the SA. It turns out - // that doing this work in the target VM is significantly faster, - // and since interactivity when setting and clearing breakpoints is - // important, the solution which resulted in more C/C++ code was used. - // - - // Source file name - JNIEXPORT char saCmdBkptSrcFileName[SA_CMD_BUF_SIZE]; - - // Package name ('/' as separator instead of '.') - JNIEXPORT char saCmdBkptPkgName[SA_CMD_BUF_SIZE]; - - // Line number - JNIEXPORT int32_t saCmdBkptLineNumber; - - // Output back to SA: indicator whether the last failure of a - // breakpoint toggle command was really an error or just a lack of - // debug information covering the requested line. 0 if not error. - // Valid only if saCmdResult != 0. - JNIEXPORT int32_t saCmdBkptResWasError; - - // Output back to SA: resulting line number at which the breakpoint - // was set or cleared (valid only if saCmdResult == 0) - JNIEXPORT int32_t saCmdBkptResLineNumber; - - // Output back to SA: resulting byte code index at which the - // breakpoint was set or cleared (valid only if saCmdResult == 0) - JNIEXPORT int32_t saCmdBkptResBCI; - - // Output back to SA: indicator whether the breakpoint operation - // resulted in a set or cleared breakpoint; nonzero if set, zero if - // cleared (valid only if saCmdResult == 0) - JNIEXPORT int32_t saCmdBkptResWasSet; - - // Output back to SA: method name the breakpoint was set in (valid - // only if saCmdResult == 0) - JNIEXPORT char saCmdBkptResMethodName[SA_CMD_BUF_SIZE]; - - // Output back to SA: method signature (JNI style) the breakpoint - // was set in (valid only if saCmdResult == 0) - JNIEXPORT char saCmdBkptResMethodSig[SA_CMD_BUF_SIZE]; -} - -// Internal state -static JavaVM* jvm = NULL; -static JVMDI_Interface_1* jvmdi = NULL; -static jthread debugThreadObj = NULL; -static bool suspended = false; -static vector suspendedThreads; -static JVMDI_RawMonitor eventLock = NULL; - -class MonitorLocker { -private: - JVMDI_RawMonitor lock; -public: - MonitorLocker(JVMDI_RawMonitor lock) { - this->lock = lock; - if (lock != NULL) { - jvmdi->RawMonitorEnter(lock); - } - } - ~MonitorLocker() { - if (lock != NULL) { - jvmdi->RawMonitorExit(lock); - } - } -}; - -class JvmdiDeallocator { -private: - void* ptr; -public: - JvmdiDeallocator(void* ptr) { - this->ptr = ptr; - } - ~JvmdiDeallocator() { - jvmdi->Deallocate((jbyte*) ptr); - } -}; - -class JvmdiRefListDeallocator { -private: - JNIEnv* env; - jobject* refList; - jint refCount; -public: - JvmdiRefListDeallocator(JNIEnv* env, jobject* refList, jint refCount) { - this->env = env; - this->refList = refList; - this->refCount = refCount; - } - ~JvmdiRefListDeallocator() { - for (int i = 0; i < refCount; i++) { - env->DeleteGlobalRef(refList[i]); - } - jvmdi->Deallocate((jbyte*) refList); - } -}; - -static void -stop(char* msg) { - fprintf(stderr, "%s", msg); - fprintf(stderr, "\n"); - exit(1); -} - -// This fills in the command result error message, sets the command -// result to -1, and clears the pending command flag -static void -reportErrorToSA(const char* str, ...) { - va_list varargs; - va_start(varargs, str); - vsnprintf(saCmdResultErrMsg, sizeof(saCmdResultErrMsg), str, varargs); - va_end(varargs); - saCmdResult = -1; - saCmdPending = 0; -} - -static bool -packageNameMatches(char* clazzName, char* pkg) { - int pkgLen = strlen(pkg); - int clazzNameLen = strlen(clazzName); - - if (pkgLen >= clazzNameLen + 1) { - return false; - } - - if (strncmp(clazzName, pkg, pkgLen)) { - return false; - } - - // Ensure that '/' is the next character if non-empty package name - int l = pkgLen; - if (l > 0) { - if (clazzName[l] != '/') { - return false; - } - l++; - } - // Ensure that there are no more trailing slashes - while (l < clazzNameLen) { - if (clazzName[l++] == '/') { - return false; - } - } - return true; -} - -static void -executeOneCommand(JNIEnv* env) { - switch (saCmdType) { - case SA_CMD_SUSPEND_ALL: { - if (suspended) { - reportErrorToSA("Target process already suspended"); - return; - } - - // We implement this by getting all of the threads and calling - // SuspendThread on each one, except for the thread object - // corresponding to this thread. Each thread for which the call - // succeeded (i.e., did not return JVMDI_ERROR_INVALID_THREAD) - // is added to a list which is remembered for later resumption. - // Note that this currently has race conditions since a thread - // might be started after we call GetAllThreads and since a - // thread for which we got an error earlier might be resumed by - // the VM while we are busy suspending other threads. We could - // solve this by looping until there are no more threads we can - // suspend, but a more robust and scalable solution is to add - // this functionality to the JVMDI interface (i.e., - // "suspendAll"). Probably need to provide an exclude list for - // such a routine. - jint threadCount; - jthread* threads; - if (jvmdi->GetAllThreads(&threadCount, &threads) != JVMDI_ERROR_NONE) { - reportErrorToSA("Error while getting thread list"); - return; - } - - - for (int i = 0; i < threadCount; i++) { - jthread thr = threads[i]; - if (!env->IsSameObject(thr, debugThreadObj)) { - jvmdiError err = jvmdi->SuspendThread(thr); - if (err == JVMDI_ERROR_NONE) { - // Remember this thread and do not free it - suspendedThreads.push_back(thr); - continue; - } else { - fprintf(stderr, " SA: Error %d while suspending thread\n", err); - // FIXME: stop, resume all threads, report error - } - } - env->DeleteGlobalRef(thr); - } - - // Free up threads - jvmdi->Deallocate((jbyte*) threads); - - // Suspension is complete - suspended = true; - break; - } - - case SA_CMD_RESUME_ALL: { - if (!suspended) { - reportErrorToSA("Target process already suspended"); - return; - } - - saCmdResult = 0; - bool errorOccurred = false; - jvmdiError firstError; - for (int i = 0; i < suspendedThreads.size(); i++) { - jthread thr = suspendedThreads[i]; - jvmdiError err = jvmdi->ResumeThread(thr); - env->DeleteGlobalRef(thr); - if (err != JVMDI_ERROR_NONE) { - if (!errorOccurred) { - errorOccurred = true; - firstError = err; - } - } - } - suspendedThreads.clear(); - suspended = false; - if (errorOccurred) { - reportErrorToSA("Error %d while resuming threads", firstError); - return; - } - break; - } - - case SA_CMD_TOGGLE_BREAKPOINT: { - saCmdBkptResWasError = 1; - - // Search line number info for all loaded classes - jint classCount; - jclass* classes; - - jvmdiError glcRes = jvmdi->GetLoadedClasses(&classCount, &classes); - if (glcRes != JVMDI_ERROR_NONE) { - reportErrorToSA("Error %d while getting loaded classes", glcRes); - return; - } - JvmdiRefListDeallocator rld(env, (jobject*) classes, classCount); - - bool done = false; - bool gotOne = false; - jclass targetClass; - jmethodID targetMethod; - jlocation targetLocation; - jint targetLineNumber; - - for (int i = 0; i < classCount && !done; i++) { - fflush(stderr); - jclass clazz = classes[i]; - char* srcName; - jvmdiError sfnRes = jvmdi->GetSourceFileName(clazz, &srcName); - if (sfnRes == JVMDI_ERROR_NONE) { - JvmdiDeallocator de1(srcName); - if (!strcmp(srcName, saCmdBkptSrcFileName)) { - // Got a match. Now see whether the package name of the class also matches - char* clazzName; - jvmdiError sigRes = jvmdi->GetClassSignature(clazz, &clazzName); - if (sigRes != JVMDI_ERROR_NONE) { - reportErrorToSA("Error %d while getting a class's signature", sigRes); - return; - } - JvmdiDeallocator de2(clazzName); - if (packageNameMatches(clazzName + 1, saCmdBkptPkgName)) { - // Iterate through all methods - jint methodCount; - jmethodID* methods; - if (jvmdi->GetClassMethods(clazz, &methodCount, &methods) != JVMDI_ERROR_NONE) { - reportErrorToSA("Error while getting methods of class %s", clazzName); - return; - } - JvmdiDeallocator de3(methods); - for (int j = 0; j < methodCount && !done; j++) { - jmethodID m = methods[j]; - jint entryCount; - JVMDI_line_number_entry* table; - jvmdiError lnRes = jvmdi->GetLineNumberTable(clazz, m, &entryCount, &table); - if (lnRes == JVMDI_ERROR_NONE) { - JvmdiDeallocator de4(table); - // Look for line number greater than or equal to requested line - for (int k = 0; k < entryCount && !done; k++) { - JVMDI_line_number_entry& entry = table[k]; - if (entry.line_number >= saCmdBkptLineNumber && - (!gotOne || entry.line_number < targetLineNumber)) { - gotOne = true; - targetClass = clazz; - targetMethod = m; - targetLocation = entry.start_location; - targetLineNumber = entry.line_number; - done = (targetLineNumber == saCmdBkptLineNumber); - } - } - } else if (lnRes != JVMDI_ERROR_ABSENT_INFORMATION) { - reportErrorToSA("Unexpected error %d while fetching line number table", lnRes); - return; - } - } - } - } - } else if (sfnRes != JVMDI_ERROR_ABSENT_INFORMATION) { - reportErrorToSA("Unexpected error %d while fetching source file name", sfnRes); - return; - } - } - - bool wasSet = true; - if (gotOne) { - // Really toggle this breakpoint - jvmdiError bpRes; - bpRes = jvmdi->SetBreakpoint(targetClass, targetMethod, targetLocation); - if (bpRes == JVMDI_ERROR_DUPLICATE) { - bpRes = jvmdi->ClearBreakpoint(targetClass, targetMethod, targetLocation); - wasSet = false; - } - if (bpRes != JVMDI_ERROR_NONE) { - reportErrorToSA("Unexpected error %d while setting or clearing breakpoint at bci %d, line %d", - bpRes, targetLocation, targetLineNumber); - return; - } - } else { - saCmdBkptResWasError = 0; - reportErrorToSA("No debug information found covering this line"); - return; - } - - // Provide result - saCmdBkptResLineNumber = targetLineNumber; - saCmdBkptResBCI = targetLocation; - saCmdBkptResWasSet = (wasSet ? 1 : 0); - { - char* methodName; - char* methodSig; - if (jvmdi->GetMethodName(targetClass, targetMethod, &methodName, &methodSig) - == JVMDI_ERROR_NONE) { - JvmdiDeallocator mnd(methodName); - JvmdiDeallocator msd(methodSig); - strncpy(saCmdBkptResMethodName, methodName, SA_CMD_BUF_SIZE); - strncpy(saCmdBkptResMethodSig, methodSig, SA_CMD_BUF_SIZE); - } else { - strncpy(saCmdBkptResMethodName, "", SA_CMD_BUF_SIZE); - strncpy(saCmdBkptResMethodSig, "", SA_CMD_BUF_SIZE); - } - } - break; - } - - default: - reportErrorToSA("Command %d not yet supported", saCmdType); - return; - } - - // Successful command execution - saCmdResult = 0; - saCmdPending = 0; -} - -static void -saCommandThread(void *arg) { - JNIEnv* env = NULL; - if (jvm->GetEnv((void **) &env, JNI_VERSION_1_2) != JNI_OK) { - stop("Error while starting Serviceability Agent " - "command thread: could not get JNI environment"); - } - - while (1) { - // Wait for command - while (!saCmdPending) { - SLEEP(); - } - - executeOneCommand(env); - } -} - -static void -saEventHook(JNIEnv *env, JVMDI_Event *event) -{ - MonitorLocker ml(eventLock); - - saEventKind = event->kind; - - if (event->kind == JVMDI_EVENT_VM_INIT) { - // Create event lock - if (jvmdi->CreateRawMonitor("Serviceability Agent Event Lock", &eventLock) - != JVMDI_ERROR_NONE) { - stop("Unable to create Serviceability Agent's event lock"); - } - // Start thread which receives commands from the SA. - jclass threadClass = env->FindClass("java/lang/Thread"); - if (threadClass == NULL) stop("Unable to find class java/lang/Thread"); - jstring threadName = env->NewStringUTF("Serviceability Agent Command Thread"); - if (threadName == NULL) stop("Unable to allocate debug thread name"); - jmethodID ctor = env->GetMethodID(threadClass, "", "(Ljava/lang/String;)V"); - if (ctor == NULL) stop("Unable to find appropriate constructor for java/lang/Thread"); - // Allocate thread object - jthread thr = (jthread) env->NewObject(threadClass, ctor, threadName); - if (thr == NULL) stop("Unable to allocate debug thread's java/lang/Thread instance"); - // Remember which thread this is - debugThreadObj = env->NewGlobalRef(thr); - if (debugThreadObj == NULL) stop("Unable to allocate global ref for debug thread object"); - // Start thread - jvmdiError err; - if ((err = jvmdi->RunDebugThread(thr, &saCommandThread, NULL, JVMDI_THREAD_NORM_PRIORITY)) - != JVMDI_ERROR_NONE) { - char buf[256]; - sprintf(buf, "Error %d while starting debug thread", err); - stop(buf); - } - // OK, initialization is done - return; - } - - if (!saAttached) { - return; - } - - switch (event->kind) { - case JVMDI_EVENT_EXCEPTION: { - fprintf(stderr, "SA: Exception thrown -- ignoring\n"); - saExceptionThread = event->u.exception.thread; - saExceptionClass = event->u.exception.clazz; - saExceptionMethod = event->u.exception.method; - saExceptionLocation = event->u.exception.location; - saExceptionException = event->u.exception.exception; - saExceptionCatchClass = event->u.exception.catch_clazz; - saExceptionCatchClass = event->u.exception.catch_clazz; - saExceptionCatchMethod = event->u.exception.catch_method; - saExceptionCatchLocation = event->u.exception.catch_location; - // saEventPending = 1; - break; - } - - case JVMDI_EVENT_BREAKPOINT: { - saBreakpointThread = event->u.breakpoint.thread; - saBreakpointClass = event->u.breakpoint.clazz; - saBreakpointMethod = event->u.breakpoint.method; - saBreakpointLocation = event->u.breakpoint.location; - saEventPending = 1; - break; - } - - default: - break; - } - - while (saAttached && saEventPending) { - SLEEP(); - } -} - -extern "C" { -JNIEXPORT jint JNICALL -JVM_OnLoad(JavaVM *vm, char *options, void *reserved) -{ - jvm = vm; - if (jvm->GetEnv((void**) &jvmdi, JVMDI_VERSION_1) != JNI_OK) { - return -1; - } - if (jvmdi->SetEventHook(&saEventHook) != JVMDI_ERROR_NONE) { - return -1; - } - return 0; -} -}; diff -r a413bcd552a4 -r 5fc51c1ecdeb agent/src/share/native/jvmdi/sa.dsp --- a/agent/src/share/native/jvmdi/sa.dsp Tue Mar 05 21:58:51 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,105 +0,0 @@ -# Microsoft Developer Studio Project File - Name="sa" - Package Owner=<4> -# Microsoft Developer Studio Generated Build File, Format Version 6.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 - -CFG=sa - Win32 Debug -!MESSAGE This is not a valid makefile. To build this project using NMAKE, -!MESSAGE use the Export Makefile command and run -!MESSAGE -!MESSAGE NMAKE /f "sa.mak". -!MESSAGE -!MESSAGE You can specify a configuration when running NMAKE -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "sa.mak" CFG="sa - Win32 Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "sa - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") -!MESSAGE "sa - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") -!MESSAGE - -# Begin Project -# PROP AllowPerConfigDependencies 0 -# PROP Scc_ProjName "" -# PROP Scc_LocalPath "" -CPP=cl.exe -MTL=midl.exe -RSC=rc.exe - -!IF "$(CFG)" == "sa - Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "Release" -# PROP BASE Intermediate_Dir "Release" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "Release" -# PROP Intermediate_Dir "Release" -# PROP Target_Dir "" -# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "SA_EXPORTS" /YX /FD /c -# ADD CPP /nologo /MT /W3 /GX /O2 /I "D:\jdk1.4\include" /I "D:\jdk1.4\include\win32" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "SA_EXPORTS" /YX /FD /c -# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 -# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 -# ADD BASE RSC /l 0x409 /d "NDEBUG" -# ADD RSC /l 0x409 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 - -!ELSEIF "$(CFG)" == "sa - Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "Debug" -# PROP BASE Intermediate_Dir "Debug" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "Debug" -# PROP Intermediate_Dir "Debug" -# PROP Target_Dir "" -# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "SA_EXPORTS" /YX /FD /GZ /c -# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "D:\jdk1.4\include" /I "D:\jdk1.4\include\win32" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "SA_EXPORTS" /YX /FD /GZ /c -# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 -# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 -# ADD BASE RSC /l 0x409 /d "_DEBUG" -# ADD RSC /l 0x409 /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept - -!ENDIF - -# Begin Target - -# Name "sa - Win32 Release" -# Name "sa - Win32 Debug" -# Begin Group "Source Files" - -# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" -# Begin Source File - -SOURCE=.\sa.cpp -# End Source File -# End Group -# Begin Group "Header Files" - -# PROP Default_Filter "h;hpp;hxx;hm;inl" -# End Group -# Begin Group "Resource Files" - -# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" -# End Group -# End Target -# End Project diff -r a413bcd552a4 -r 5fc51c1ecdeb agent/src/share/native/jvmdi/sa.dsw --- a/agent/src/share/native/jvmdi/sa.dsw Tue Mar 05 21:58:51 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,29 +0,0 @@ -Microsoft Developer Studio Workspace File, Format Version 6.00 -# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! - -############################################################################### - -Project: "sa"=.\sa.dsp - Package Owner=<4> - -Package=<5> -{{{ -}}} - -Package=<4> -{{{ -}}} - -############################################################################### - -Global: - -Package=<5> -{{{ -}}} - -Package=<3> -{{{ -}}} - -############################################################################### - diff -r a413bcd552a4 -r 5fc51c1ecdeb agent/src/share/native/jvmdi/sa.hpp --- a/agent/src/share/native/jvmdi/sa.hpp Tue Mar 05 21:58:51 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,30 +0,0 @@ -/* - * Copyright (c) 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. - * - * 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 "jni.h" - -extern "C" { -JNIEXPORT jint JNICALL -JVM_OnLoad(JavaVM *vm, char *options, void *reserved); -} diff -r a413bcd552a4 -r 5fc51c1ecdeb make/Makefile --- a/make/Makefile Tue Mar 05 21:58:51 2013 +0100 +++ b/make/Makefile Tue Mar 05 23:44:54 2013 +0100 @@ -1,5 +1,5 @@ # -# Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -87,7 +87,6 @@ # Typical C1/C2 targets made available with this Makefile C1_VM_TARGETS=product1 fastdebug1 optimized1 jvmg1 C2_VM_TARGETS=product fastdebug optimized jvmg -KERNEL_VM_TARGETS=productkernel fastdebugkernel optimizedkernel jvmgkernel ZERO_VM_TARGETS=productzero fastdebugzero optimizedzero jvmgzero SHARK_VM_TARGETS=productshark fastdebugshark optimizedshark jvmgshark MINIMAL1_VM_TARGETS=productminimal1 fastdebugminimal1 jvmgminimal1 @@ -168,11 +167,6 @@ $(CD) $(GAMMADIR)/make; \ $(MAKE) BUILD_FLAVOR=$@ VM_TARGET=$@ generic_build2 $(ALT_OUT) -$(KERNEL_VM_TARGETS): - $(CD) $(GAMMADIR)/make; \ - $(MAKE) BUILD_FLAVOR=$(@:%kernel=%) VM_TARGET=$@ \ - generic_buildkernel $(ALT_OUT) - $(ZERO_VM_TARGETS): $(CD) $(GAMMADIR)/make; \ $(MAKE) BUILD_FLAVOR=$(@:%zero=%) VM_TARGET=$@ \ @@ -230,24 +224,6 @@ $(MAKE_ARGS) $(VM_TARGET) endif -generic_buildkernel: - $(MKDIR) -p $(OUTPUTDIR) -ifeq ($(OSNAME),windows) - ifeq ($(ARCH_DATA_MODEL), 32) - $(CD) $(OUTPUTDIR); \ - $(NMAKE) -f $(ABS_OS_MAKEFILE) \ - Variant=kernel \ - WorkSpace=$(ABS_GAMMADIR) \ - BootStrapDir=$(ABS_BOOTDIR) \ - BuildUser=$(USERNAME) \ - $(MAKE_ARGS) $(VM_TARGET:%kernel=%) - else - @$(ECHO) "No kernel ($(VM_TARGET)) for ARCH_DATA_MODEL=$(ARCH_DATA_MODEL)" - endif -else - @$(ECHO) "No kernel ($(VM_TARGET)) for OS_NAME=$(OSNAME)" -endif - generic_buildzero: $(MKDIR) -p $(OUTPUTDIR) $(CD) $(OUTPUTDIR); \ @@ -327,13 +303,11 @@ DOCS_DIR=$(OUTPUTDIR)/$(VM_PLATFORM)_docs C1_BASE_DIR=$(OUTPUTDIR)/$(VM_PLATFORM)_compiler1 C2_BASE_DIR=$(OUTPUTDIR)/$(VM_PLATFORM)_compiler2 -KERNEL_BASE_DIR=$(OUTPUTDIR)/$(VM_PLATFORM)_kernel ZERO_BASE_DIR=$(OUTPUTDIR)/$(VM_PLATFORM)_zero SHARK_BASE_DIR=$(OUTPUTDIR)/$(VM_PLATFORM)_shark GRAAL_BASE_DIR=$(OUTPUTDIR)/$(VM_PLATFORM)_graal C1_DIR=$(C1_BASE_DIR)/$(VM_SUBDIR) C2_DIR=$(C2_BASE_DIR)/$(VM_SUBDIR) -KERNEL_DIR=$(KERNEL_BASE_DIR)/$(VM_SUBDIR) ZERO_DIR=$(ZERO_BASE_DIR)/$(VM_SUBDIR) SHARK_DIR=$(SHARK_BASE_DIR)/$(VM_SUBDIR) MINIMAL1_BASE_DIR=$(OUTPUTDIR)/$(VM_PLATFORM)_minimal1 @@ -348,10 +322,6 @@ MISC_DIR=$(C1_DIR) GEN_DIR=$(C1_BASE_DIR)/generated endif -ifeq ($(JVM_VARIANT_KERNEL), true) - MISC_DIR=$(C2_DIR) - GEN_DIR=$(C2_BASE_DIR)/generated -endif ifeq ($(JVM_VARIANT_ZEROSHARK), true) MISC_DIR=$(SHARK_DIR) GEN_DIR=$(SHARK_BASE_DIR)/generated @@ -401,16 +371,6 @@ $(install-file) $(EXPORT_SERVER_DIR)/%.map: $(C2_DIR)/%.map $(install-file) - -# Kernel files always come from kernel area -$(EXPORT_KERNEL_DIR)/%.diz: $(KERNEL_DIR)/%.diz - $(install-file) -$(EXPORT_KERNEL_DIR)/%.dll: $(KERNEL_DIR)/%.dll - $(install-file) -$(EXPORT_KERNEL_DIR)/%.pdb: $(KERNEL_DIR)/%.pdb - $(install-file) -$(EXPORT_KERNEL_DIR)/%.map: $(KERNEL_DIR)/%.map - $(install-file) endif # Minimal JVM files always come from minimal area @@ -519,9 +479,6 @@ $(EXPORT_LIB_DIR)/%.jar: $(GEN_DIR)/%.jar $(install-file) -$(EXPORT_JRE_LIB_DIR)/%.jar: $(GEN_DIR)/%.jar - $(install-file) - # Include files (jvmti.h, jvmticmlr.h, jni.h, $(JDK_INCLUDE_SUBDIR)/jni_md.h, jmm.h, jfr.h) $(EXPORT_INCLUDE_DIR)/%: $(GEN_DIR)/jvmtifiles/% $(install-file) @@ -553,7 +510,7 @@ $(install-file) # Xusage file -$(EXPORT_SERVER_DIR)/Xusage.txt $(EXPORT_CLIENT_DIR)/Xusage.txt $(EXPORT_KERNEL_DIR)/Xusage.txt $(EXPORT_MINIMAL_DIR)/Xusage.txt: $(XUSAGE) +$(EXPORT_SERVER_DIR)/Xusage.txt $(EXPORT_CLIENT_DIR)/Xusage.txt $(EXPORT_MINIMAL_DIR)/Xusage.txt: $(XUSAGE) $(prep-target) $(RM) $@.temp $(SED) 's/\(separated by \)[;:]/\1$(PATH_SEP)/g' $< > $@.temp @@ -566,7 +523,6 @@ clean_build: $(RM) -r $(C1_DIR) $(RM) -r $(C2_DIR) - $(RM) -r $(KERNEL_DIR) $(RM) -r $(ZERO_DIR) $(RM) -r $(SHARK_DIR) $(RM) -r $(MINIMAL1_DIR) @@ -602,10 +558,6 @@ $(JDK_IMAGE_DIR)/bin/java -d$(ARCH_DATA_MODEL) -server -Xinternalversion $(JDK_IMAGE_DIR)/bin/java -d$(ARCH_DATA_MODEL) -server -version endif - ifeq ($(JVM_VARIANT_KERNEL), true) - $(JDK_IMAGE_DIR)/bin/java -d$(ARCH_DATA_MODEL) -kernel -Xinternalversion - $(JDK_IMAGE_DIR)/bin/java -d$(ARCH_DATA_MODEL) -kernel -version - endif copy_product_jdk:: $(RM) -r $(JDK_IMAGE_DIR) @@ -681,7 +633,6 @@ @$(ECHO) "Other targets are:" @$(ECHO) " $(C1_VM_TARGETS)" @$(ECHO) " $(C2_VM_TARGETS)" - @$(ECHO) " $(KERNEL_VM_TARGETS)" @$(ECHO) " $(MINIMAL1_VM_TARGETS)" # Variable help (only common ones used by this workspace) @@ -777,8 +728,8 @@ include $(GAMMADIR)/make/jprt.gmk .PHONY: all world clobber clean help $(C1_VM_TARGETS) $(C2_VM_TARGETS) \ - $(KERNEL_VM_TARGETS) $(MINIMAL1_VM_TARGETS) \ - generic_build1 generic_build2 generic_buildkernel generic_buildminimal1 generic_export \ + $(MINIMAL1_VM_TARGETS) \ + generic_build1 generic_build2 generic_buildminimal1 generic_export \ export_product export_fastdebug export_debug export_optimized \ export_jdk_product export_jdk_fastdebug export_jdk_debug \ create_jdk copy_jdk update_jdk test_jdk \ diff -r a413bcd552a4 -r 5fc51c1ecdeb make/bsd/makefiles/defs.make --- a/make/bsd/makefiles/defs.make Tue Mar 05 21:58:51 2013 +0100 +++ b/make/bsd/makefiles/defs.make Tue Mar 05 23:44:54 2013 +0100 @@ -157,8 +157,6 @@ EXPORT_CLIENT_DIR = $(EXPORT_JRE_LIB_ARCH_DIR)/client EXPORT_MINIMAL_DIR = $(EXPORT_JRE_LIB_ARCH_DIR)/minimal -EXPORT_LIST += $(EXPORT_JRE_LIB_DIR)/wb.jar - ifeq ($(findstring true, $(JVM_VARIANT_SERVER) $(JVM_VARIANT_ZERO) $(JVM_VARIANT_ZEROSHARK)), true) EXPORT_LIST += $(EXPORT_SERVER_DIR)/Xusage.txt EXPORT_LIST += $(EXPORT_SERVER_DIR)/libjvm.$(LIBRARY_SUFFIX) diff -r a413bcd552a4 -r 5fc51c1ecdeb make/bsd/makefiles/dtrace.make --- a/make/bsd/makefiles/dtrace.make Tue Mar 05 21:58:51 2013 +0100 +++ b/make/bsd/makefiles/dtrace.make Tue Mar 05 23:44:54 2013 +0100 @@ -1,5 +1,5 @@ # -# Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -25,10 +25,9 @@ # Rules to build jvm_db/dtrace, used by vm.make # We build libjvm_dtrace/libjvm_db/dtrace for COMPILER1 and COMPILER2 -# but not for CORE or KERNEL configurations. +# but not for CORE configuration. ifneq ("${TYPE}", "CORE") -ifneq ("${TYPE}", "KERNEL") ifeq ($(OS_VENDOR), Darwin) # we build dtrace for macosx using USDT2 probes @@ -280,13 +279,6 @@ endif # ifeq ($(OS_VENDOR), Darwin) -else # KERNEL build - -dtraceCheck: - $(QUIETLY) echo "**NOTICE** Dtrace support disabled for KERNEL builds" - -endif # ifneq ("${TYPE}", "KERNEL") - else # CORE build dtraceCheck: diff -r a413bcd552a4 -r 5fc51c1ecdeb make/bsd/makefiles/mapfile-vers-debug --- a/make/bsd/makefiles/mapfile-vers-debug Tue Mar 05 21:58:51 2013 +0100 +++ b/make/bsd/makefiles/mapfile-vers-debug Tue Mar 05 23:44:54 2013 +0100 @@ -188,6 +188,7 @@ JVM_IsSilentCompiler; JVM_IsSupportedJNIVersion; JVM_IsThreadAlive; + JVM_IsVMGeneratedMethodIx; JVM_LatestUserDefinedLoader; JVM_Listen; JVM_LoadClass0; diff -r a413bcd552a4 -r 5fc51c1ecdeb make/bsd/makefiles/mapfile-vers-product --- a/make/bsd/makefiles/mapfile-vers-product Tue Mar 05 21:58:51 2013 +0100 +++ b/make/bsd/makefiles/mapfile-vers-product Tue Mar 05 23:44:54 2013 +0100 @@ -188,6 +188,7 @@ JVM_IsSilentCompiler; JVM_IsSupportedJNIVersion; JVM_IsThreadAlive; + JVM_IsVMGeneratedMethodIx; JVM_LatestUserDefinedLoader; JVM_Listen; JVM_LoadClass0; diff -r a413bcd552a4 -r 5fc51c1ecdeb make/bsd/makefiles/minimal1.make --- a/make/bsd/makefiles/minimal1.make Tue Mar 05 21:58:51 2013 +0100 +++ b/make/bsd/makefiles/minimal1.make Tue Mar 05 23:44:54 2013 +0100 @@ -30,7 +30,7 @@ INCLUDE_JNI_CHECK ?= false INCLUDE_SERVICES ?= false INCLUDE_MANAGEMENT ?= false -INCLUDE_ALTERNATE_GCS ?= false +INCLUDE_ALL_GCS ?= false INCLUDE_NMT ?= false INCLUDE_CDS ?= false diff -r a413bcd552a4 -r 5fc51c1ecdeb make/bsd/makefiles/vm.make --- a/make/bsd/makefiles/vm.make Tue Mar 05 21:58:51 2013 +0100 +++ b/make/bsd/makefiles/vm.make Tue Mar 05 23:44:54 2013 +0100 @@ -94,7 +94,12 @@ # This is VERY important! The version define must only be supplied to vm_version.o # If not, ccache will not re-use the cache at all, since the version string might contain # a time and date. -vm_version.o: CXXFLAGS += ${JRE_VERSION} +CXXFLAGS/vm_version.o += ${JRE_VERSION} + +CXXFLAGS/BYFILE = $(CXXFLAGS/$@) + +# File specific flags +CXXFLAGS += $(CXXFLAGS/BYFILE) ifdef DEFAULT_LIBPATH CXXFLAGS += -DDEFAULT_LIBPATH="\"$(DEFAULT_LIBPATH)\"" @@ -343,9 +348,6 @@ # Serviceability agent include $(MAKEFILES_DIR)/saproc.make -# Whitebox testing API -include $(MAKEFILES_DIR)/wb.make - #---------------------------------------------------------------------- ifeq ($(OS_VENDOR), Darwin) @@ -353,10 +355,10 @@ dsymutil $(LIBJVM) # no libjvm_db for macosx -build: $(LIBJVM) $(LAUNCHER) $(LIBJSIG) $(BUILDLIBSAPROC) dtraceCheck $(LIBJVM).dSYM $(WB_JAR) +build: $(LIBJVM) $(LAUNCHER) $(LIBJSIG) $(BUILDLIBSAPROC) dtraceCheck $(LIBJVM).dSYM echo "Doing vm.make build:" else -build: $(LIBJVM) $(LAUNCHER) $(LIBJSIG) $(LIBJVM_DB) $(BUILDLIBSAPROC) $(WB_JAR) +build: $(LIBJVM) $(LAUNCHER) $(LIBJSIG) $(LIBJVM_DB) $(BUILDLIBSAPROC) endif install: install_jvm install_jsig install_saproc diff -r a413bcd552a4 -r 5fc51c1ecdeb make/bsd/makefiles/wb.make --- a/make/bsd/makefiles/wb.make Tue Mar 05 21:58:51 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,46 +0,0 @@ -# -# Copyright (c) 2012, 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. -# -# - -# Rules to build whitebox testing library, used by vm.make -WB = wb - -WBSRCDIR = $(GAMMADIR)/src/share/tools/whitebox - -WB_JAR = $(GENERATED)/$(WB).jar - -WB_JAVA_SRCS = $(shell find $(WBSRCDIR) -name '*.java') -WB_JAVA_CLASSDIR = $(GENERATED)/wb/classes - -WB_JAVA_CLASSES = $(patsubst $(WBSRCDIR)/%,$(WB_JAVA_CLASSDIR)/%, \ - $(patsubst %.java,%.class,$(WB_JAVA_SRCS))) - -$(WB_JAVA_CLASSDIR)/%.class: $(WBSRCDIR)/%.java $(WB_JAVA_CLASSDIR) - $(REMOTE) $(COMPILE.JAVAC) -sourcepath $(WBSRCDIR) -nowarn -d $(WB_JAVA_CLASSDIR) $< - -$(WB_JAR): $(WB_JAVA_CLASSES) - $(QUIETLY) $(REMOTE) $(RUN.JAR) cf $@ -C $(WB_JAVA_CLASSDIR)/ . - -$(WB_JAVA_CLASSDIR): - $(QUIETLY) mkdir -p $@ - diff -r a413bcd552a4 -r 5fc51c1ecdeb make/excludeSrc.make --- a/make/excludeSrc.make Tue Mar 05 21:58:51 2013 +0100 +++ b/make/excludeSrc.make Tue Mar 05 23:44:54 2013 +0100 @@ -72,15 +72,13 @@ Src_Files_EXCLUDE += metaspaceShared.cpp endif -ifeq ($(INCLUDE_ALTERNATE_GCS), false) - CXXFLAGS += -DINCLUDE_ALTERNATE_GCS=0 - CFLAGS += -DINCLUDE_ALTERNATE_GCS=0 +ifeq ($(INCLUDE_ALL_GCS), false) + CXXFLAGS += -DINCLUDE_ALL_GCS=0 + CFLAGS += -DINCLUDE_ALL_GCS=0 - CXXFLAGS += -DSERIALGC - CFLAGS += -DSERIALGC Src_Files_EXCLUDE += \ cmsAdaptiveSizePolicy.cpp cmsCollectorPolicy.cpp \ - cmsGCAdaptivePolicyCounters.cpp cmsLockVerifier.cpp cmsPermGen.cpp compactibleFreeListSpace.cpp \ + cmsGCAdaptivePolicyCounters.cpp cmsLockVerifier.cpp compactibleFreeListSpace.cpp \ concurrentMarkSweepGeneration.cpp concurrentMarkSweepThread.cpp \ freeChunk.cpp adaptiveFreeList.cpp promotionInfo.cpp vmCMSOperations.cpp collectionSetChooser.cpp \ concurrentG1Refine.cpp concurrentG1RefineThread.cpp concurrentMark.cpp concurrentMarkThread.cpp \ @@ -93,11 +91,11 @@ gcTaskManager.cpp gcTaskThread.cpp objectStartArray.cpp parallelScavengeHeap.cpp parMarkBitMap.cpp \ pcTasks.cpp psAdaptiveSizePolicy.cpp psCompactionManager.cpp psGCAdaptivePolicyCounters.cpp \ psGenerationCounters.cpp psMarkSweep.cpp psMarkSweepDecorator.cpp psOldGen.cpp psParallelCompact.cpp \ - psPermGen.cpp psPromotionLAB.cpp psPromotionManager.cpp psScavenge.cpp psTasks.cpp psVirtualspace.cpp \ + psPromotionLAB.cpp psPromotionManager.cpp psScavenge.cpp psTasks.cpp psVirtualspace.cpp \ psYoungGen.cpp vmPSOperations.cpp asParNewGeneration.cpp parCardTableModRefBS.cpp \ parGCAllocBuffer.cpp parNewGeneration.cpp mutableSpace.cpp gSpaceCounters.cpp allocationStats.cpp \ spaceCounters.cpp gcAdaptivePolicyCounters.cpp mutableNUMASpace.cpp immutableSpace.cpp \ - immutableSpace.cpp g1MemoryPool.cpp psMemoryPool.cpp yieldWorkingGroup.cpp g1Log.cpp + immutableSpace.cpp g1MemoryPool.cpp psMemoryPool.cpp yieldingWorkGroup.cpp g1Log.cpp endif ifeq ($(INCLUDE_NMT), false) diff -r a413bcd552a4 -r 5fc51c1ecdeb make/hotspot_version --- a/make/hotspot_version Tue Mar 05 21:58:51 2013 +0100 +++ b/make/hotspot_version Tue Mar 05 23:44:54 2013 +0100 @@ -35,7 +35,7 @@ HS_MAJOR_VER=25 HS_MINOR_VER=0 -HS_BUILD_NUMBER=17 +HS_BUILD_NUMBER=21 JDK_MAJOR_VER=1 JDK_MINOR_VER=8 diff -r a413bcd552a4 -r 5fc51c1ecdeb make/linux/makefiles/defs.make --- a/make/linux/makefiles/defs.make Tue Mar 05 21:58:51 2013 +0100 +++ b/make/linux/makefiles/defs.make Tue Mar 05 23:44:54 2013 +0100 @@ -258,8 +258,6 @@ EXPORT_CLIENT_DIR = $(EXPORT_JRE_LIB_ARCH_DIR)/client EXPORT_MINIMAL_DIR = $(EXPORT_JRE_LIB_ARCH_DIR)/minimal -EXPORT_LIST += $(EXPORT_JRE_LIB_DIR)/wb.jar - ifeq ($(findstring true, $(JVM_VARIANT_SERVER) $(JVM_VARIANT_ZERO) $(JVM_VARIANT_ZEROSHARK)), true) EXPORT_LIST += $(EXPORT_SERVER_DIR)/Xusage.txt EXPORT_LIST += $(EXPORT_SERVER_DIR)/libjvm.$(LIBRARY_SUFFIX) diff -r a413bcd552a4 -r 5fc51c1ecdeb make/linux/makefiles/mapfile-vers-debug --- a/make/linux/makefiles/mapfile-vers-debug Tue Mar 05 21:58:51 2013 +0100 +++ b/make/linux/makefiles/mapfile-vers-debug Tue Mar 05 23:44:54 2013 +0100 @@ -184,6 +184,7 @@ JVM_IsSilentCompiler; JVM_IsSupportedJNIVersion; JVM_IsThreadAlive; + JVM_IsVMGeneratedMethodIx; JVM_LatestUserDefinedLoader; JVM_Listen; JVM_LoadClass0; diff -r a413bcd552a4 -r 5fc51c1ecdeb make/linux/makefiles/mapfile-vers-product --- a/make/linux/makefiles/mapfile-vers-product Tue Mar 05 21:58:51 2013 +0100 +++ b/make/linux/makefiles/mapfile-vers-product Tue Mar 05 23:44:54 2013 +0100 @@ -184,6 +184,7 @@ JVM_IsSilentCompiler; JVM_IsSupportedJNIVersion; JVM_IsThreadAlive; + JVM_IsVMGeneratedMethodIx; JVM_LatestUserDefinedLoader; JVM_Listen; JVM_LoadClass0; diff -r a413bcd552a4 -r 5fc51c1ecdeb make/linux/makefiles/minimal1.make --- a/make/linux/makefiles/minimal1.make Tue Mar 05 21:58:51 2013 +0100 +++ b/make/linux/makefiles/minimal1.make Tue Mar 05 23:44:54 2013 +0100 @@ -30,7 +30,7 @@ INCLUDE_JNI_CHECK ?= false INCLUDE_SERVICES ?= false INCLUDE_MANAGEMENT ?= false -INCLUDE_ALTERNATE_GCS ?= false +INCLUDE_ALL_GCS ?= false INCLUDE_NMT ?= false INCLUDE_CDS ?= false diff -r a413bcd552a4 -r 5fc51c1ecdeb make/linux/makefiles/vm.make --- a/make/linux/makefiles/vm.make Tue Mar 05 21:58:51 2013 +0100 +++ b/make/linux/makefiles/vm.make Tue Mar 05 23:44:54 2013 +0100 @@ -100,7 +100,13 @@ # This is VERY important! The version define must only be supplied to vm_version.o # If not, ccache will not re-use the cache at all, since the version string might contain # a time and date. -vm_version.o: CXXFLAGS += ${JRE_VERSION} +CXXFLAGS/vm_version.o += ${JRE_VERSION} + +CXXFLAGS/BYFILE = $(CXXFLAGS/$@) + +# File specific flags +CXXFLAGS += $(CXXFLAGS/BYFILE) + ifndef JAVASE_EMBEDDED ifneq (${ARCH},arm) @@ -386,12 +392,9 @@ # Serviceability agent include $(MAKEFILES_DIR)/saproc.make -# Whitebox testing API -include $(MAKEFILES_DIR)/wb.make - #---------------------------------------------------------------------- -build: $(LIBJVM) $(LAUNCHER) $(LIBJSIG) $(LIBJVM_DB) $(BUILDLIBSAPROC) dtraceCheck $(WB_JAR) +build: $(LIBJVM) $(LAUNCHER) $(LIBJSIG) $(LIBJVM_DB) $(BUILDLIBSAPROC) dtraceCheck install: install_jvm install_jsig install_saproc diff -r a413bcd552a4 -r 5fc51c1ecdeb make/linux/makefiles/wb.make --- a/make/linux/makefiles/wb.make Tue Mar 05 21:58:51 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,46 +0,0 @@ -# -# Copyright (c) 2012, 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. -# -# - -# Rules to build whitebox testing library, used by vm.make -WB = wb - -WBSRCDIR = $(GAMMADIR)/src/share/tools/whitebox - -WB_JAR = $(GENERATED)/$(WB).jar - -WB_JAVA_SRCS = $(shell find $(WBSRCDIR) -name '*.java') -WB_JAVA_CLASSDIR = $(GENERATED)/wb/classes - -WB_JAVA_CLASSES = $(patsubst $(WBSRCDIR)/%,$(WB_JAVA_CLASSDIR)/%, \ - $(patsubst %.java,%.class,$(WB_JAVA_SRCS))) - -$(WB_JAVA_CLASSDIR)/%.class: $(WBSRCDIR)/%.java $(WB_JAVA_CLASSDIR) - $(REMOTE) $(COMPILE.JAVAC) -sourcepath $(WBSRCDIR) -nowarn -d $(WB_JAVA_CLASSDIR) $< - -$(WB_JAR): $(WB_JAVA_CLASSES) - $(QUIETLY) $(REMOTE) $(RUN.JAR) cf $@ -C $(WB_JAVA_CLASSDIR)/ . - -$(WB_JAVA_CLASSDIR): - $(QUIETLY) mkdir -p $@ - diff -r a413bcd552a4 -r 5fc51c1ecdeb make/sa.files --- a/make/sa.files Tue Mar 05 21:58:51 2013 +0100 +++ b/make/sa.files Tue Mar 05 23:44:54 2013 +0100 @@ -24,10 +24,7 @@ # This filelist macro is included in platform specific sa.make # included all packages/*.java. package list can be generated by -# $(GAMMADIR)/agent/make/build-pkglist. Then manually removed all -# classes in sun.jvm.hotspot.ui (and subpackages), all ui classes -# in sun.jvm.hotspot.bugspot/hotspot and SPARC and x86 disassembler -# classes and sun.jvm.hotspot.utilities.soql. +# $(GAMMADIR)/agent/make/build-pkglist. # define AGENT_DIR before including this file in sa.make @@ -40,8 +37,6 @@ $(AGENT_SRC_DIR)/sun/jvm/hotspot/*.java \ $(AGENT_SRC_DIR)/sun/jvm/hotspot/asm/*.java \ $(AGENT_SRC_DIR)/sun/jvm/hotspot/asm/sparc/*.java \ -$(AGENT_SRC_DIR)/sun/jvm/hotspot/bugspot/*.java \ -$(AGENT_SRC_DIR)/sun/jvm/hotspot/bugspot/tree/*.java \ $(AGENT_SRC_DIR)/sun/jvm/hotspot/c1/*.java \ $(AGENT_SRC_DIR)/sun/jvm/hotspot/ci/*.java \ $(AGENT_SRC_DIR)/sun/jvm/hotspot/code/*.java \ @@ -82,7 +77,6 @@ $(AGENT_SRC_DIR)/sun/jvm/hotspot/gc_interface/*.java \ $(AGENT_SRC_DIR)/sun/jvm/hotspot/interpreter/*.java \ $(AGENT_SRC_DIR)/sun/jvm/hotspot/jdi/*.java \ -$(AGENT_SRC_DIR)/sun/jvm/hotspot/livejvm/*.java \ $(AGENT_SRC_DIR)/sun/jvm/hotspot/memory/*.java \ $(AGENT_SRC_DIR)/sun/jvm/hotspot/oops/*.java \ $(AGENT_SRC_DIR)/sun/jvm/hotspot/opto/*.java \ diff -r a413bcd552a4 -r 5fc51c1ecdeb make/solaris/Makefile --- a/make/solaris/Makefile Tue Mar 05 21:58:51 2013 +0100 +++ b/make/solaris/Makefile Tue Mar 05 23:44:54 2013 +0100 @@ -1,5 +1,5 @@ # -# Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -157,14 +157,12 @@ SUBDIRS_C2 = $(addprefix $(OSNAME)_$(BUILDARCH)_compiler2/,$(TARGETS)) SUBDIRS_TIERED = $(addprefix $(OSNAME)_$(BUILDARCH)_tiered/,$(TARGETS)) SUBDIRS_CORE = $(addprefix $(OSNAME)_$(BUILDARCH)_core/,$(TARGETS)) -SUBDIRS_KERNEL = $(addprefix $(OSNAME)_$(BUILDARCH)_kernel/,$(TARGETS)) SUBDIRS_GRAAL = $(addprefix $(OSNAME)_$(BUILDARCH)_graal/,$(TARGETS)) TARGETS_C2 = $(TARGETS) TARGETS_C1 = $(addsuffix 1,$(TARGETS)) TARGETS_TIERED = $(addsuffix tiered,$(TARGETS)) TARGETS_CORE = $(addsuffix core,$(TARGETS)) -TARGETS_KERNEL = $(addsuffix kernel,$(TARGETS)) TARGETS_GRAAL = $(addsuffix graal,$(TARGETS)) BUILDTREE_MAKE = $(GAMMADIR)/make/$(OSNAME)/makefiles/buildtree.make @@ -232,10 +230,6 @@ $(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks $(BUILDTREE) VARIANT=core -$(SUBDIRS_KERNEL): $(BUILDTREE_MAKE) - $(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks - $(BUILDTREE) VARIANT=kernel - $(SUBDIRS_GRAAL): $(BUILDTREE_MAKE) $(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks $(BUILDTREE) VARIANT=graal @@ -278,15 +272,6 @@ cd $(OSNAME)_$(BUILDARCH)_core/$(patsubst %core,%,$@) && $(MAKE) $(MFLAGS) install endif -$(TARGETS_KERNEL): $(SUBDIRS_KERNEL) - cd $(OSNAME)_$(BUILDARCH)_kernel/$(patsubst %kernel,%,$@) && $(MAKE) $(MFLAGS) -ifeq ($(TEST_IN_BUILD),true) - cd $(OSNAME)_$(BUILDARCH)_kernel/$(patsubst %kernel,%,$@) && ./test_gamma -endif -ifdef INSTALL - cd $(OSNAME)_$(BUILDARCH)_kernel/$(patsubst %kernel,%,$@) && $(MAKE) $(MFLAGS) install -endif - $(TARGETS_GRAAL): $(SUBDIRS_GRAAL) cd $(OSNAME)_$(BUILDARCH)_graal/$(patsubst %graal,%,$@) && $(MAKE) $(MFLAGS) ifdef INSTALL @@ -297,7 +282,6 @@ tree: $(SUBDIRS_C2) tree1: $(SUBDIRS_C1) treecore: $(SUBDIRS_CORE) -treekernel: $(SUBDIRS_KERNEL) treegraal: $(SUBDIRS_GRAAL) # Doc target. This is the same for all build options. @@ -318,10 +302,10 @@ clean_docs: rm -rf $(SUBDIR_DOCS) -clean_compiler1 clean_compiler2 clean_core clean_kernel clean_graal: +clean_compiler1 clean_compiler2 clean_core clean_graal: rm -rf $(OSNAME)_$(BUILDARCH)_$(subst clean_,,$@) -clean: clean_compiler2 clean_compiler1 clean_core clean_docs clean_kernel clean_graal +clean: clean_compiler2 clean_compiler1 clean_core clean_docs clean_graal include $(GAMMADIR)/make/cscope.make diff -r a413bcd552a4 -r 5fc51c1ecdeb make/solaris/makefiles/defs.make --- a/make/solaris/makefiles/defs.make Tue Mar 05 21:58:51 2013 +0100 +++ b/make/solaris/makefiles/defs.make Tue Mar 05 23:44:54 2013 +0100 @@ -187,8 +187,6 @@ endif endif -EXPORT_LIST += $(EXPORT_JRE_LIB_DIR)/wb.jar - EXPORT_SERVER_DIR = $(EXPORT_JRE_LIB_ARCH_DIR)/server EXPORT_CLIENT_DIR = $(EXPORT_JRE_LIB_ARCH_DIR)/client diff -r a413bcd552a4 -r 5fc51c1ecdeb make/solaris/makefiles/dtrace.make --- a/make/solaris/makefiles/dtrace.make Tue Mar 05 21:58:51 2013 +0100 +++ b/make/solaris/makefiles/dtrace.make Tue Mar 05 23:44:54 2013 +0100 @@ -1,5 +1,5 @@ # -# Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -25,10 +25,9 @@ # Rules to build jvm_db/dtrace, used by vm.make # We build libjvm_dtrace/libjvm_db/dtrace for COMPILER1 and COMPILER2 -# but not for CORE or KERNEL configurations. +# but not for CORE configuration. ifneq ("${TYPE}", "CORE") -ifneq ("${TYPE}", "KERNEL") ifdef USE_GCC @@ -362,13 +361,6 @@ endif # ifdef USE_GCC -else # KERNEL build - -dtraceCheck: - $(QUIETLY) echo "**NOTICE** Dtrace support disabled for KERNEL builds" - -endif # ifneq ("${TYPE}", "KERNEL") - else # CORE build dtraceCheck: diff -r a413bcd552a4 -r 5fc51c1ecdeb make/solaris/makefiles/kernel.make --- a/make/solaris/makefiles/kernel.make Tue Mar 05 21:58:51 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,32 +0,0 @@ -# -# Copyright (c) 2007, 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. -# -# -# -# Sets make macros for making kernel version of VM. -# This target on solaris is just tempoarily for debugging the kernel build. - -TYPE=KERNEL - -VM_SUBDIR = client - -CFLAGS += -DKERNEL diff -r a413bcd552a4 -r 5fc51c1ecdeb make/solaris/makefiles/mapfile-vers --- a/make/solaris/makefiles/mapfile-vers Tue Mar 05 21:58:51 2013 +0100 +++ b/make/solaris/makefiles/mapfile-vers Tue Mar 05 23:44:54 2013 +0100 @@ -184,6 +184,7 @@ JVM_IsSilentCompiler; JVM_IsSupportedJNIVersion; JVM_IsThreadAlive; + JVM_IsVMGeneratedMethodIx; JVM_LatestUserDefinedLoader; JVM_Listen; JVM_LoadClass0; diff -r a413bcd552a4 -r 5fc51c1ecdeb make/solaris/makefiles/vm.make --- a/make/solaris/makefiles/vm.make Tue Mar 05 21:58:51 2013 +0100 +++ b/make/solaris/makefiles/vm.make Tue Mar 05 23:44:54 2013 +0100 @@ -88,7 +88,13 @@ # This is VERY important! The version define must only be supplied to vm_version.o # If not, ccache will not re-use the cache at all, since the version string might contain # a time and date. -vm_version.o: CXXFLAGS += ${JRE_VERSION} +CXXFLAGS/vm_version.o += ${JRE_VERSION} + +CXXFLAGS/BYFILE = $(CXXFLAGS/$@) + +# File specific flags +CXXFLAGS += $(CXXFLAGS/BYFILE) + # CFLAGS_WARN holds compiler options to suppress/enable warnings. CFLAGS += $(CFLAGS_WARN) @@ -347,12 +353,9 @@ # Serviceability agent include $(MAKEFILES_DIR)/saproc.make -# Whitebox testing API -include $(MAKEFILES_DIR)/wb.make - #---------------------------------------------------------------------- -build: $(LIBJVM) $(LAUNCHER) $(LIBJSIG) $(LIBJVM_DB) $(LIBJVM_DTRACE) $(BUILDLIBSAPROC) dtraceCheck $(WB_JAR) +build: $(LIBJVM) $(LAUNCHER) $(LIBJSIG) $(LIBJVM_DB) $(LIBJVM_DTRACE) $(BUILDLIBSAPROC) dtraceCheck install: install_jvm install_jsig install_saproc diff -r a413bcd552a4 -r 5fc51c1ecdeb make/solaris/makefiles/wb.make --- a/make/solaris/makefiles/wb.make Tue Mar 05 21:58:51 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,46 +0,0 @@ -# -# Copyright (c) 2012, 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. -# - -# Rules to build whitebox testing library, used by vm.make - -WB = wb - -WBSRCDIR = $(GAMMADIR)/src/share/tools/whitebox - -WB_JAR = $(GENERATED)/$(WB).jar - -WB_JAVA_SRCS = $(shell find $(WBSRCDIR) -name '*.java') -WB_JAVA_CLASSDIR = $(GENERATED)/wb/classes - -WB_JAVA_CLASSES = $(patsubst $(WBSRCDIR)/%,$(WB_JAVA_CLASSDIR)/%, \ - $(patsubst %.java,%.class,$(WB_JAVA_SRCS))) - -$(WB_JAVA_CLASSDIR)/%.class: $(WBSRCDIR)/%.java $(WB_JAVA_CLASSDIR) - $(REMOTE) $(COMPILE.JAVAC) -sourcepath $(WBSRCDIR) -nowarn -d $(WB_JAVA_CLASSDIR) $< - -$(WB_JAR): $(WB_JAVA_CLASSES) - $(QUIETLY) $(REMOTE) $(RUN.JAR) cf $@ -C $(WB_JAVA_CLASSDIR)/ . - -$(WB_JAVA_CLASSDIR): - $(QUIETLY) mkdir -p $@ - diff -r a413bcd552a4 -r 5fc51c1ecdeb make/windows/build.bat --- a/make/windows/build.bat Tue Mar 05 21:58:51 2013 +0100 +++ b/make/windows/build.bat Tue Mar 05 23:44:54 2013 +0100 @@ -1,6 +1,6 @@ @echo off REM -REM Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. +REM Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. REM DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. REM REM This code is free software; you can redistribute it and/or modify it @@ -67,7 +67,6 @@ :test1 if "%2" == "core" goto test2 -if "%2" == "kernel" goto test2 if "%2" == "compiler1" goto test2 if "%2" == "compiler2" goto test2 if "%2" == "tiered" goto test2 @@ -109,7 +108,7 @@ echo. echo where: echo flavor is "product", "debug" or "fastdebug", -echo version is "core", "kernel", "compiler1", "compiler2", or "tiered", +echo version is "core", "compiler1", "compiler2", or "tiered", echo workspace is source directory without trailing slash, echo bootstrap_dir is a full path to a JDK in which bin/java echo and bin/javac are present and working, and build_id is an diff -r a413bcd552a4 -r 5fc51c1ecdeb make/windows/create_obj_files.sh --- a/make/windows/create_obj_files.sh Tue Mar 05 21:58:51 2013 +0100 +++ b/make/windows/create_obj_files.sh Tue Mar 05 23:44:54 2013 +0100 @@ -1,5 +1,5 @@ # -# Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -107,7 +107,6 @@ # Include dirs per type. case "${TYPE}" in "core") Src_Dirs="${CORE_PATHS}" ;; - "kernel") Src_Dirs="${BASE_PATHS} ${COMPILER1_PATHS}" ;; "compiler1") Src_Dirs="${CORE_PATHS} ${COMPILER1_PATHS}" ;; "compiler2") Src_Dirs="${CORE_PATHS} ${COMPILER2_PATHS}" ;; "tiered") Src_Dirs="${CORE_PATHS} ${COMPILER1_PATHS} ${COMPILER2_PATHS}" ;; @@ -120,16 +119,12 @@ SHARK_SPECIFIC_FILES="shark" ZERO_SPECIFIC_FILES="zero" -# These files need to be excluded when building the kernel target. -KERNEL_EXCLUDED_FILES="attachListener.cpp attachListener_windows.cpp metaspaceShared_${Platform_arch_model}.cpp forte.cpp fprofiler.cpp heapDumper.cpp heapInspection.cpp jniCheck.cpp jvmtiCodeBlobEvents.cpp jvmtiExtensions.cpp jvmtiImpl.cpp jvmtiRawMonitor.cpp jvmtiTagMap.cpp jvmtiTrace.cpp vmStructs.cpp g1MemoryPool.cpp psMemoryPool.cpp gcAdaptivePolicyCounters.cpp concurrentGCThread.cpp metaspaceShared.cpp mutableNUMASpace.cpp allocationStats.cpp gSpaceCounters.cpp immutableSpace.cpp mutableSpace.cpp spaceCounters.cpp yieldingWorkgroup.cpp" - # Always exclude these. Src_Files_EXCLUDE="jsig.c jvmtiEnvRecommended.cpp jvmtiEnvStub.cpp" # Exclude per type. case "${TYPE}" in "core") Src_Files_EXCLUDE="${Src_Files_EXCLUDE} ${COMPILER1_SPECIFIC_FILES} ${COMPILER2_SPECIFIC_FILES} ${ZERO_SPECIFIC_FILES} ${SHARK_SPECIFIC_FILES} ciTypeFlow.cpp" ;; - "kernel") Src_Files_EXCLUDE="${Src_Files_EXCLUDE} ${COMPILER2_SPECIFIC_FILES} ${ZERO_SPECIFIC_FILES} ${SHARK_SPECIFIC_FILES} ${KERNEL_EXCLUDED_FILES} ciTypeFlow.cpp" ;; "compiler1") Src_Files_EXCLUDE="${Src_Files_EXCLUDE} ${COMPILER2_SPECIFIC_FILES} ${ZERO_SPECIFIC_FILES} ${SHARK_SPECIFIC_FILES} ciTypeFlow.cpp" ;; "compiler2") Src_Files_EXCLUDE="${Src_Files_EXCLUDE} ${COMPILER1_SPECIFIC_FILES} ${ZERO_SPECIFIC_FILES} ${SHARK_SPECIFIC_FILES}" ;; "tiered") Src_Files_EXCLUDE="${Src_Files_EXCLUDE} ${ZERO_SPECIFIC_FILES} ${SHARK_SPECIFIC_FILES}" ;; diff -r a413bcd552a4 -r 5fc51c1ecdeb make/windows/makefiles/debug.make --- a/make/windows/makefiles/debug.make Tue Mar 05 21:58:51 2013 +0100 +++ b/make/windows/makefiles/debug.make Tue Mar 05 23:44:54 2013 +0100 @@ -33,7 +33,7 @@ BUILD_PCH_FILE=_build_pch_file.obj !endif -default:: $(BUILD_PCH_FILE) $(AOUT) launcher checkAndBuildSA wb +default:: $(BUILD_PCH_FILE) $(AOUT) launcher checkAndBuildSA !include ../local.make !include compile.make @@ -72,4 +72,3 @@ !include $(WorkSpace)/make/windows/makefiles/shared.make !include $(WorkSpace)/make/windows/makefiles/sa.make !include $(WorkSpace)/make/windows/makefiles/launcher.make -!include $(WorkSpace)/make/windows/makefiles/wb.make diff -r a413bcd552a4 -r 5fc51c1ecdeb make/windows/makefiles/defs.make --- a/make/windows/makefiles/defs.make Tue Mar 05 21:58:51 2013 +0100 +++ b/make/windows/makefiles/defs.make Tue Mar 05 23:44:54 2013 +0100 @@ -1,5 +1,5 @@ # -# Copyright (c) 2006, 2012, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -157,7 +157,7 @@ MAKE_ARGS += RM="$(RM)" MAKE_ARGS += ZIPEXE=$(ZIPEXE) -# On 32 bit windows we build server, client and kernel, on 64 bit just server. +# On 32 bit windows we build server and client, on 64 bit just server. ifeq ($(JVM_VARIANTS),) ifeq ($(ARCH_DATA_MODEL), 32) JVM_VARIANTS:=client,server @@ -250,7 +250,6 @@ EXPORT_SERVER_DIR = $(EXPORT_JRE_BIN_DIR)/server EXPORT_CLIENT_DIR = $(EXPORT_JRE_BIN_DIR)/client -EXPORT_KERNEL_DIR = $(EXPORT_JRE_BIN_DIR)/kernel ifeq ($(JVM_VARIANT_SERVER),true) EXPORT_LIST += $(EXPORT_SERVER_DIR)/Xusage.txt @@ -277,20 +276,6 @@ endif endif endif -ifeq ($(JVM_VARIANT_KERNEL),true) - EXPORT_LIST += $(EXPORT_KERNEL_DIR)/Xusage.txt - EXPORT_LIST += $(EXPORT_KERNEL_DIR)/jvm.$(LIBRARY_SUFFIX) - ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1) - ifeq ($(ZIP_DEBUGINFO_FILES),1) - EXPORT_LIST += $(EXPORT_KERNEL_DIR)/jvm.diz - else - EXPORT_LIST += $(EXPORT_KERNEL_DIR)/jvm.pdb - EXPORT_LIST += $(EXPORT_KERNEL_DIR)/jvm.map - endif - endif -endif - -EXPORT_LIST += $(EXPORT_JRE_LIB_DIR)/wb.jar ifeq ($(BUILD_WIN_SA), 1) EXPORT_LIST += $(EXPORT_JRE_BIN_DIR)/sawindbg.$(LIBRARY_SUFFIX) diff -r a413bcd552a4 -r 5fc51c1ecdeb make/windows/makefiles/fastdebug.make --- a/make/windows/makefiles/fastdebug.make Tue Mar 05 21:58:51 2013 +0100 +++ b/make/windows/makefiles/fastdebug.make Tue Mar 05 23:44:54 2013 +0100 @@ -33,7 +33,7 @@ BUILD_PCH_FILE=_build_pch_file.obj !endif -default:: $(BUILD_PCH_FILE) $(AOUT) launcher checkAndBuildSA wb +default:: $(BUILD_PCH_FILE) $(AOUT) launcher checkAndBuildSA !include ../local.make !include compile.make @@ -71,4 +71,3 @@ !include $(WorkSpace)/make/windows/makefiles/shared.make !include $(WorkSpace)/make/windows/makefiles/sa.make !include $(WorkSpace)/make/windows/makefiles/launcher.make -!include $(WorkSpace)/make/windows/makefiles/wb.make diff -r a413bcd552a4 -r 5fc51c1ecdeb make/windows/makefiles/product.make --- a/make/windows/makefiles/product.make Tue Mar 05 21:58:51 2013 +0100 +++ b/make/windows/makefiles/product.make Tue Mar 05 23:44:54 2013 +0100 @@ -32,7 +32,7 @@ BUILD_PCH_FILE=_build_pch_file.obj !endif -default:: $(BUILD_PCH_FILE) $(AOUT) launcher checkAndBuildSA wb +default:: $(BUILD_PCH_FILE) $(AOUT) launcher checkAndBuildSA !include ../local.make !include compile.make @@ -82,4 +82,3 @@ !include $(WorkSpace)/make/windows/makefiles/shared.make !include $(WorkSpace)/make/windows/makefiles/sa.make !include $(WorkSpace)/make/windows/makefiles/launcher.make -!include $(WorkSpace)/make/windows/makefiles/wb.make diff -r a413bcd552a4 -r 5fc51c1ecdeb make/windows/makefiles/projectcreator.make --- a/make/windows/makefiles/projectcreator.make Tue Mar 05 21:58:51 2013 +0100 +++ b/make/windows/makefiles/projectcreator.make Tue Mar 05 23:44:54 2013 +0100 @@ -1,5 +1,5 @@ # -# Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -170,63 +170,6 @@ $(ProjectCreatorIDEOptionsIgnoreCompiler2:TARGET=core) ################################################## -# JKERNEL specific options -################################################## -ProjectCreatorIDEOptions=$(ProjectCreatorIDEOptions) \ - -define_kernel KERNEL \ -$(ProjectCreatorIDEOptionsIgnoreCompiler2:TARGET=kernel) \ - -ignorePath_kernel src/share/vm/gc_implementation/parallelScavenge \ - -ignorePath_kernel src/share/vm/gc_implementation/parNew \ - -ignorePath_kernel src/share/vm/gc_implementation/concurrentMarkSweep \ - -ignorePath_kernel src/share/vm/gc_implementation/g1 \ - -ignoreFile_kernel attachListener.cpp \ - -ignoreFile_kernel attachListener_windows.cpp \ - -ignoreFile_kernel dump.cpp \ - -ignoreFile_kernel dump_$(Platform_arch_model).cpp \ - -ignoreFile_kernel forte.cpp \ - -ignoreFile_kernel fprofiler.cpp \ - -ignoreFile_kernel heapDumper.cpp \ - -ignoreFile_kernel heapInspection.cpp \ - -ignoreFile_kernel jniCheck.cpp \ - -ignoreFile_kernel jvmtiCodeBlobEvents.cpp \ - -ignoreFile_kernel jvmtiExtensions.cpp \ - -ignoreFile_kernel jvmtiImpl.cpp \ - -ignoreFile_kernel jvmtiRawMonitor.cpp \ - -ignoreFile_kernel jvmtiTagMap.cpp \ - -ignoreFile_kernel jvmtiTrace.cpp \ - -ignoreFile_kernel jvmtiTrace.hpp \ - -ignoreFile_kernel restore.cpp \ - -ignoreFile_kernel serialize.cpp \ - -ignoreFile_kernel vmStructs.cpp \ - -ignoreFile_kernel g1MemoryPool.cpp \ - -ignoreFile_kernel g1MemoryPool.hpp \ - -ignoreFile_kernel psMemoryPool.cpp \ - -ignoreFile_kernel psMemoryPool.hpp \ - -ignoreFile_kernel gcAdaptivePolicyCounters.cpp \ - -ignoreFile_kernel concurrentGCThread.cpp \ - -ignoreFile_kernel mutableNUMASpace.cpp \ - -ignoreFile_kernel ciTypeFlow.cpp \ - -ignoreFile_kernel ciTypeFlow.hpp \ - -ignoreFile_kernel oop.pcgc.inline.hpp \ - -ignoreFile_kernel oop.psgc.inline.hpp \ - -ignoreFile_kernel allocationStats.cpp \ - -ignoreFile_kernel allocationStats.hpp \ - -ignoreFile_kernel concurrentGCThread.hpp \ - -ignoreFile_kernel gSpaceCounters.cpp \ - -ignoreFile_kernel gSpaceCounters.hpp \ - -ignoreFile_kernel gcAdaptivePolicyCounters.hpp \ - -ignoreFile_kernel immutableSpace.cpp \ - -ignoreFile_kernel mutableNUMASpace.hpp \ - -ignoreFile_kernel mutableSpace.cpp \ - -ignoreFile_kernel spaceCounters.cpp \ - -ignoreFile_kernel spaceCounters.hpp \ - -ignoreFile_kernel yieldingWorkgroup.cpp \ - -ignoreFile_kernel yieldingWorkgroup.hpp \ - -ignorePath_kernel vmStructs_ \ - -ignoreFile_kernel $(Platform_arch_model).ad \ - -additionalFile_kernel gcTaskManager.hpp - -################################################## # Client(C1) compiler specific options ################################################## ProjectCreatorIDEOptions=$(ProjectCreatorIDEOptions) \ diff -r a413bcd552a4 -r 5fc51c1ecdeb make/windows/makefiles/vm.make --- a/make/windows/makefiles/vm.make Tue Mar 05 21:58:51 2013 +0100 +++ b/make/windows/makefiles/vm.make Tue Mar 05 23:44:54 2013 +0100 @@ -1,5 +1,5 @@ # -# Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -44,10 +44,6 @@ # No need to define anything, CORE is defined as !COMPILER1 && !COMPILER2 !endif -!if "$(Variant)" == "kernel" -CXX_FLAGS=$(CXX_FLAGS) /D "KERNEL" -!endif - !if "$(Variant)" == "compiler1" CXX_FLAGS=$(CXX_FLAGS) /D "COMPILER1" !endif diff -r a413bcd552a4 -r 5fc51c1ecdeb make/windows/makefiles/wb.make --- a/make/windows/makefiles/wb.make Tue Mar 05 21:58:51 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,54 +0,0 @@ -# -# Copyright (c) 2012, 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. -# -# - -# This makefile is used to build the whitebox testing lib -# and compile the tests which use it - -!include $(WorkSpace)/make/windows/makefiles/rules.make - -WBSRCDIR = $(WorkSpace)/src/share/tools/whitebox - -# turn GENERATED into a windows path to get sane dependencies -WB_CLASSES=$(GENERATED:/=\)\wb\classes -WB_JAR=$(GENERATED:/=\)\wb.jar - -# call recursive make to do wildcard expansion -.SUFFIXES : .java .class -wb_java_srcs: $(WorkSpace)\src\share\tools\whitebox\sun\hotspot\*.java $(WB_CLASSES) - $(MAKE) -f $(WorkSpace)\make\windows\makefiles\$(BUILD_FLAVOR).make $(**:.java=.class) - - -{$(WorkSpace)\src\share\tools\whitebox\sun\hotspot}.java.class:: - $(COMPILE_JAVAC) -sourcepath $(WBSRCDIR) -d $(WB_CLASSES) $< - -$(WB_JAR): wb_java_srcs - $(RUN_JAR) cf $@ -C $(WB_CLASSES) . - -# turn $@ to a unix path because mkdir in PATH is cygwin/mks mkdir -$(WB_CLASSES): - mkdir -p $(@:\=/) - -# main target to build wb -wb: $(WB_JAR) - diff -r a413bcd552a4 -r 5fc51c1ecdeb src/cpu/sparc/vm/c1_CodeStubs_sparc.cpp --- a/src/cpu/sparc/vm/c1_CodeStubs_sparc.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/cpu/sparc/vm/c1_CodeStubs_sparc.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -30,10 +30,11 @@ #include "c1/c1_Runtime1.hpp" #include "nativeInst_sparc.hpp" #include "runtime/sharedRuntime.hpp" +#include "utilities/macros.hpp" #include "vmreg_sparc.inline.hpp" -#ifndef SERIALGC +#if INCLUDE_ALL_GCS #include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp" -#endif +#endif // INCLUDE_ALL_GCS #define __ ce->masm()-> @@ -420,7 +421,7 @@ /////////////////////////////////////////////////////////////////////////////////// -#ifndef SERIALGC +#if INCLUDE_ALL_GCS void G1PreBarrierStub::emit_code(LIR_Assembler* ce) { // At this point we know that marking is in progress. @@ -483,7 +484,7 @@ __ delayed()->nop(); } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS /////////////////////////////////////////////////////////////////////////////////// #undef __ diff -r a413bcd552a4 -r 5fc51c1ecdeb src/cpu/sparc/vm/c1_Runtime1_sparc.cpp --- a/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -35,6 +35,7 @@ #include "runtime/sharedRuntime.hpp" #include "runtime/signature.hpp" #include "runtime/vframeArray.hpp" +#include "utilities/macros.hpp" #include "vmreg_sparc.inline.hpp" // Implementation of StubAssembler @@ -822,7 +823,7 @@ } break; -#ifndef SERIALGC +#if INCLUDE_ALL_GCS case g1_pre_barrier_slow_id: { // G4: previous value of memory BarrierSet* bs = Universe::heap()->barrier_set(); @@ -984,7 +985,7 @@ __ delayed()->restore(); } break; -#endif // !SERIALGC +#endif // INCLUDE_ALL_GCS default: { __ set_info("unimplemented entry", dont_gc_arguments); diff -r a413bcd552a4 -r 5fc51c1ecdeb src/cpu/sparc/vm/c2_globals_sparc.hpp --- a/src/cpu/sparc/vm/c2_globals_sparc.hpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/cpu/sparc/vm/c2_globals_sparc.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -43,7 +43,7 @@ #else define_pd_global(bool, ProfileInterpreter, true); #endif // CC_INTERP -define_pd_global(bool, TieredCompilation, trueInTiered); +define_pd_global(bool, TieredCompilation, false); define_pd_global(intx, CompileThreshold, 10000); define_pd_global(intx, BackEdgeThreshold, 140000); diff -r a413bcd552a4 -r 5fc51c1ecdeb src/cpu/sparc/vm/cppInterpreter_sparc.cpp --- a/src/cpu/sparc/vm/cppInterpreter_sparc.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/cpu/sparc/vm/cppInterpreter_sparc.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -45,6 +45,7 @@ #include "runtime/timer.hpp" #include "runtime/vframeArray.hpp" #include "utilities/debug.hpp" +#include "utilities/macros.hpp" #ifdef SHARK #include "shark/shark_globals.hpp" #endif @@ -551,7 +552,7 @@ } address InterpreterGenerator::generate_Reference_get_entry(void) { -#ifndef SERIALGC +#if INCLUDE_ALL_GCS if (UseG1GC) { // We need to generate have a routine that generates code to: // * load the value in the referent field @@ -563,7 +564,7 @@ // field as live. Unimplemented(); } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS // If G1 is not enabled then attempt to go through the accessor entry point // Reference.get is an accessor diff -r a413bcd552a4 -r 5fc51c1ecdeb src/cpu/sparc/vm/frame_sparc.cpp --- a/src/cpu/sparc/vm/frame_sparc.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/cpu/sparc/vm/frame_sparc.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -216,6 +216,11 @@ } } + // Could just be some random pointer within the codeBlob + if (!_cb->code_contains(_pc)) { + return false; + } + // Entry frame checks if (is_entry_frame()) { // an entry frame must have a valid fp. diff -r a413bcd552a4 -r 5fc51c1ecdeb src/cpu/sparc/vm/macroAssembler_sparc.cpp --- a/src/cpu/sparc/vm/macroAssembler_sparc.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/cpu/sparc/vm/macroAssembler_sparc.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -36,11 +36,12 @@ #include "runtime/os.hpp" #include "runtime/sharedRuntime.hpp" #include "runtime/stubRoutines.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/g1/g1CollectedHeap.inline.hpp" #include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp" #include "gc_implementation/g1/heapRegion.hpp" -#endif +#endif // INCLUDE_ALL_GCS #ifdef PRODUCT #define BLOCK_COMMENT(str) /* nothing */ @@ -3867,7 +3868,7 @@ } /////////////////////////////////////////////////////////////////////////////////// -#ifndef SERIALGC +#if INCLUDE_ALL_GCS static address satb_log_enqueue_with_frame = NULL; static u_char* satb_log_enqueue_with_frame_end = NULL; @@ -4231,7 +4232,7 @@ bind(filtered); } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS /////////////////////////////////////////////////////////////////////////////////// void MacroAssembler::card_write_barrier_post(Register store_addr, Register new_val, Register tmp) { diff -r a413bcd552a4 -r 5fc51c1ecdeb src/cpu/sparc/vm/macroAssembler_sparc.hpp --- a/src/cpu/sparc/vm/macroAssembler_sparc.hpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/cpu/sparc/vm/macroAssembler_sparc.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -26,6 +26,7 @@ #define CPU_SPARC_VM_MACROASSEMBLER_SPARC_HPP #include "asm/assembler.hpp" +#include "utilities/macros.hpp" // promises that the system will not use traps 16-31 #define ST_RESERVED_FOR_USER_0 0x10 @@ -1181,13 +1182,13 @@ void card_write_barrier_post(Register store_addr, Register new_val, Register tmp); -#ifndef SERIALGC +#if INCLUDE_ALL_GCS // General G1 pre-barrier generator. void g1_write_barrier_pre(Register obj, Register index, int offset, Register pre_val, Register tmp, bool preserve_o_regs); // General G1 post-barrier generator void g1_write_barrier_post(Register store_addr, Register new_val, Register tmp); -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS // pushes double TOS element of FPU stack on CPU stack; pops from FPU stack void push_fTOS(); diff -r a413bcd552a4 -r 5fc51c1ecdeb src/cpu/sparc/vm/templateInterpreter_sparc.cpp --- a/src/cpu/sparc/vm/templateInterpreter_sparc.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/cpu/sparc/vm/templateInterpreter_sparc.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -44,6 +44,7 @@ #include "runtime/timer.hpp" #include "runtime/vframeArray.hpp" #include "utilities/debug.hpp" +#include "utilities/macros.hpp" #ifndef CC_INTERP #ifndef FAST_DISPATCH @@ -734,7 +735,7 @@ // Method entry for java.lang.ref.Reference.get. address InterpreterGenerator::generate_Reference_get_entry(void) { -#ifndef SERIALGC +#if INCLUDE_ALL_GCS // Code: _aload_0, _getfield, _areturn // parameter size = 1 // @@ -805,7 +806,7 @@ (void) generate_normal_entry(false); return entry; } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS // If G1 is not enabled then attempt to go through the accessor entry point // Reference.get is an accessor diff -r a413bcd552a4 -r 5fc51c1ecdeb src/cpu/sparc/vm/templateTable_sparc.cpp --- a/src/cpu/sparc/vm/templateTable_sparc.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/cpu/sparc/vm/templateTable_sparc.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,6 +34,7 @@ #include "runtime/sharedRuntime.hpp" #include "runtime/stubRoutines.hpp" #include "runtime/synchronizer.hpp" +#include "utilities/macros.hpp" #ifndef CC_INTERP #define __ _masm-> @@ -53,7 +54,7 @@ assert(tmp != val && tmp != base && tmp != index, "register collision"); assert(index == noreg || offset == 0, "only one offset"); switch (barrier) { -#ifndef SERIALGC +#if INCLUDE_ALL_GCS case BarrierSet::G1SATBCT: case BarrierSet::G1SATBCTLogging: { @@ -82,7 +83,7 @@ } } break; -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS case BarrierSet::CardTableModRef: case BarrierSet::CardTableExtension: { @@ -339,8 +340,6 @@ __ bind(notInt); // __ cmp(O2, JVM_CONSTANT_String); - __ brx(Assembler::equal, true, Assembler::pt, isString); - __ delayed()->cmp(O2, JVM_CONSTANT_Object); __ brx(Assembler::notEqual, true, Assembler::pt, notString); __ delayed()->ldf(FloatRegisterImpl::S, O0, O1, Ftos_f); __ bind(isString); diff -r a413bcd552a4 -r 5fc51c1ecdeb src/cpu/x86/vm/assembler_x86.cpp --- a/src/cpu/x86/vm/assembler_x86.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/cpu/x86/vm/assembler_x86.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -36,11 +36,12 @@ #include "runtime/os.hpp" #include "runtime/sharedRuntime.hpp" #include "runtime/stubRoutines.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/g1/g1CollectedHeap.inline.hpp" #include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp" #include "gc_implementation/g1/heapRegion.hpp" -#endif +#endif // INCLUDE_ALL_GCS #ifdef PRODUCT #define BLOCK_COMMENT(str) /* nothing */ @@ -2269,10 +2270,11 @@ } void Assembler::vpermq(XMMRegister dst, XMMRegister src, int imm8, bool vector256) { - int encode = simd_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_66, VEX_OPCODE_0F_3A, true, vector256); - emit_int8(0x00); - emit_int8(0xC0 | encode); - emit_int8(imm8); + assert(VM_Version::supports_avx2(), ""); + int encode = simd_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_66, VEX_OPCODE_0F_3A, true, vector256); + emit_int8(0x00); + emit_int8(0xC0 | encode); + emit_int8(imm8); } void Assembler::pcmpestri(XMMRegister dst, Address src, int imm8) { diff -r a413bcd552a4 -r 5fc51c1ecdeb src/cpu/x86/vm/assembler_x86.hpp --- a/src/cpu/x86/vm/assembler_x86.hpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/cpu/x86/vm/assembler_x86.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -543,7 +543,7 @@ // of instructions are freely declared without the need for wrapping them an ifdef. // (Some dangerous instructions are ifdef's out of inappropriate jvm's.) // In the .cpp file the implementations are wrapped so that they are dropped out - // of the resulting jvm. This is done mostly to keep the footprint of KERNEL + // of the resulting jvm. This is done mostly to keep the footprint of MINIMAL // to the size it was prior to merging up the 32bit and 64bit assemblers. // // This does mean you'll get a linker/runtime error if you use a 64bit only instruction diff -r a413bcd552a4 -r 5fc51c1ecdeb src/cpu/x86/vm/c1_CodeStubs_x86.cpp --- a/src/cpu/x86/vm/c1_CodeStubs_x86.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/cpu/x86/vm/c1_CodeStubs_x86.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -30,10 +30,11 @@ #include "c1/c1_Runtime1.hpp" #include "nativeInst_x86.hpp" #include "runtime/sharedRuntime.hpp" +#include "utilities/macros.hpp" #include "vmreg_x86.inline.hpp" -#ifndef SERIALGC +#if INCLUDE_ALL_GCS #include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp" -#endif +#endif // INCLUDE_ALL_GCS #define __ ce->masm()-> @@ -482,7 +483,7 @@ } ///////////////////////////////////////////////////////////////////////////// -#ifndef SERIALGC +#if INCLUDE_ALL_GCS void G1PreBarrierStub::emit_code(LIR_Assembler* ce) { // At this point we know that marking is in progress. @@ -528,7 +529,7 @@ __ jmp(_continuation); } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS ///////////////////////////////////////////////////////////////////////////// #undef __ diff -r a413bcd552a4 -r 5fc51c1ecdeb src/cpu/x86/vm/c1_Runtime1_x86.cpp --- a/src/cpu/x86/vm/c1_Runtime1_x86.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/cpu/x86/vm/c1_Runtime1_x86.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -36,6 +36,7 @@ #include "runtime/sharedRuntime.hpp" #include "runtime/signature.hpp" #include "runtime/vframeArray.hpp" +#include "utilities/macros.hpp" #include "vmreg_x86.inline.hpp" @@ -1607,7 +1608,7 @@ } break; -#ifndef SERIALGC +#if INCLUDE_ALL_GCS case g1_pre_barrier_slow_id: { StubFrame f(sasm, "g1_pre_barrier", dont_gc_arguments); @@ -1804,7 +1805,7 @@ } break; -#endif // !SERIALGC +#endif // INCLUDE_ALL_GCS default: { StubFrame f(sasm, "unimplemented entry", dont_gc_arguments); diff -r a413bcd552a4 -r 5fc51c1ecdeb src/cpu/x86/vm/c2_globals_x86.hpp --- a/src/cpu/x86/vm/c2_globals_x86.hpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/cpu/x86/vm/c2_globals_x86.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -45,7 +45,7 @@ #else define_pd_global(bool, ProfileInterpreter, true); #endif // CC_INTERP -define_pd_global(bool, TieredCompilation, trueInTiered); +define_pd_global(bool, TieredCompilation, false); define_pd_global(intx, CompileThreshold, 10000); define_pd_global(intx, BackEdgeThreshold, 100000); diff -r a413bcd552a4 -r 5fc51c1ecdeb src/cpu/x86/vm/cppInterpreter_x86.cpp --- a/src/cpu/x86/vm/cppInterpreter_x86.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/cpu/x86/vm/cppInterpreter_x86.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -45,6 +45,7 @@ #include "runtime/timer.hpp" #include "runtime/vframeArray.hpp" #include "utilities/debug.hpp" +#include "utilities/macros.hpp" #ifdef SHARK #include "shark/shark_globals.hpp" #endif @@ -938,7 +939,7 @@ } address InterpreterGenerator::generate_Reference_get_entry(void) { -#ifndef SERIALGC +#if INCLUDE_ALL_GCS if (UseG1GC) { // We need to generate have a routine that generates code to: // * load the value in the referent field @@ -950,7 +951,7 @@ // field as live. Unimplemented(); } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS // If G1 is not enabled then attempt to go through the accessor entry point // Reference.get is an accessor diff -r a413bcd552a4 -r 5fc51c1ecdeb src/cpu/x86/vm/frame_x86.cpp --- a/src/cpu/x86/vm/frame_x86.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/cpu/x86/vm/frame_x86.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -91,6 +91,12 @@ return false; } } + + // Could just be some random pointer within the codeBlob + if (!_cb->code_contains(_pc)) { + return false; + } + // Entry frame checks if (is_entry_frame()) { // an entry frame must have a valid fp. diff -r a413bcd552a4 -r 5fc51c1ecdeb src/cpu/x86/vm/macroAssembler_x86.cpp --- a/src/cpu/x86/vm/macroAssembler_x86.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/cpu/x86/vm/macroAssembler_x86.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -37,11 +37,12 @@ #include "runtime/os.hpp" #include "runtime/sharedRuntime.hpp" #include "runtime/stubRoutines.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/g1/g1CollectedHeap.inline.hpp" #include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp" #include "gc_implementation/g1/heapRegion.hpp" -#endif +#endif // INCLUDE_ALL_GCS #ifdef PRODUCT #define BLOCK_COMMENT(str) /* nothing */ @@ -3207,7 +3208,7 @@ ////////////////////////////////////////////////////////////////////////////////// -#ifndef SERIALGC +#if INCLUDE_ALL_GCS void MacroAssembler::g1_write_barrier_pre(Register obj, Register pre_val, @@ -3417,7 +3418,7 @@ bind(done); } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS ////////////////////////////////////////////////////////////////////////////////// @@ -5690,7 +5691,7 @@ Address::ScaleFactor scale = Address::times_2; int stride = 8; - if (UseAVX >= 2) { + if (UseAVX >= 2 && UseSSE42Intrinsics) { Label COMPARE_WIDE_VECTORS, VECTOR_NOT_EQUAL, COMPARE_WIDE_TAIL, COMPARE_SMALL_STR; Label COMPARE_WIDE_VECTORS_LOOP, COMPARE_16_CHARS, COMPARE_INDEX_CHAR; Label COMPARE_TAIL_LONG; diff -r a413bcd552a4 -r 5fc51c1ecdeb src/cpu/x86/vm/macroAssembler_x86.hpp --- a/src/cpu/x86/vm/macroAssembler_x86.hpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/cpu/x86/vm/macroAssembler_x86.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -26,6 +26,7 @@ #define CPU_X86_VM_MACROASSEMBLER_X86_HPP #include "asm/assembler.hpp" +#include "utilities/macros.hpp" // MacroAssembler extends Assembler by frequently used macros. @@ -294,7 +295,7 @@ void store_check(Register obj); // store check for obj - register is destroyed afterwards void store_check(Register obj, Address dst); // same as above, dst is exact store location (reg. is destroyed) -#ifndef SERIALGC +#if INCLUDE_ALL_GCS void g1_write_barrier_pre(Register obj, Register pre_val, @@ -309,7 +310,7 @@ Register tmp, Register tmp2); -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS // split store_check(Register obj) to enhance instruction interleaving void store_check_part_1(Register obj); diff -r a413bcd552a4 -r 5fc51c1ecdeb src/cpu/x86/vm/templateInterpreter_x86_32.cpp --- a/src/cpu/x86/vm/templateInterpreter_x86_32.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/cpu/x86/vm/templateInterpreter_x86_32.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -44,6 +44,7 @@ #include "runtime/timer.hpp" #include "runtime/vframeArray.hpp" #include "utilities/debug.hpp" +#include "utilities/macros.hpp" #define __ _masm-> @@ -761,7 +762,7 @@ // Method entry for java.lang.ref.Reference.get. address InterpreterGenerator::generate_Reference_get_entry(void) { -#ifndef SERIALGC +#if INCLUDE_ALL_GCS // Code: _aload_0, _getfield, _areturn // parameter size = 1 // @@ -844,7 +845,7 @@ return entry; } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS // If G1 is not enabled then attempt to go through the accessor entry point // Reference.get is an accessor diff -r a413bcd552a4 -r 5fc51c1ecdeb src/cpu/x86/vm/templateInterpreter_x86_64.cpp --- a/src/cpu/x86/vm/templateInterpreter_x86_64.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/cpu/x86/vm/templateInterpreter_x86_64.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -45,6 +45,7 @@ #include "runtime/timer.hpp" #include "runtime/vframeArray.hpp" #include "utilities/debug.hpp" +#include "utilities/macros.hpp" #define __ _masm-> @@ -773,7 +774,7 @@ // Method entry for java.lang.ref.Reference.get. address InterpreterGenerator::generate_Reference_get_entry(void) { -#ifndef SERIALGC +#if INCLUDE_ALL_GCS // Code: _aload_0, _getfield, _areturn // parameter size = 1 // @@ -852,7 +853,7 @@ return entry; } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS // If G1 is not enabled then attempt to go through the accessor entry point // Reference.get is an accessor diff -r a413bcd552a4 -r 5fc51c1ecdeb src/cpu/x86/vm/templateTable_x86_32.cpp --- a/src/cpu/x86/vm/templateTable_x86_32.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/cpu/x86/vm/templateTable_x86_32.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -35,6 +35,7 @@ #include "runtime/sharedRuntime.hpp" #include "runtime/stubRoutines.hpp" #include "runtime/synchronizer.hpp" +#include "utilities/macros.hpp" #ifndef CC_INTERP #define __ _masm-> @@ -125,7 +126,7 @@ bool precise) { assert(val == noreg || val == rax, "parameter is just for looks"); switch (barrier) { -#ifndef SERIALGC +#if INCLUDE_ALL_GCS case BarrierSet::G1SATBCT: case BarrierSet::G1SATBCTLogging: { @@ -164,7 +165,7 @@ } break; -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS case BarrierSet::CardTableModRef: case BarrierSet::CardTableExtension: { diff -r a413bcd552a4 -r 5fc51c1ecdeb src/cpu/x86/vm/templateTable_x86_64.cpp --- a/src/cpu/x86/vm/templateTable_x86_64.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/cpu/x86/vm/templateTable_x86_64.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -35,6 +35,7 @@ #include "runtime/sharedRuntime.hpp" #include "runtime/stubRoutines.hpp" #include "runtime/synchronizer.hpp" +#include "utilities/macros.hpp" #ifndef CC_INTERP @@ -136,7 +137,7 @@ bool precise) { assert(val == noreg || val == rax, "parameter is just for looks"); switch (barrier) { -#ifndef SERIALGC +#if INCLUDE_ALL_GCS case BarrierSet::G1SATBCT: case BarrierSet::G1SATBCTLogging: { @@ -167,7 +168,7 @@ } break; -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS case BarrierSet::CardTableModRef: case BarrierSet::CardTableExtension: { diff -r a413bcd552a4 -r 5fc51c1ecdeb src/cpu/zero/vm/assembler_zero.cpp --- a/src/cpu/zero/vm/assembler_zero.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/cpu/zero/vm/assembler_zero.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -36,11 +36,12 @@ #include "runtime/os.hpp" #include "runtime/sharedRuntime.hpp" #include "runtime/stubRoutines.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/g1/g1CollectedHeap.inline.hpp" #include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp" #include "gc_implementation/g1/heapRegion.hpp" -#endif +#endif // INCLUDE_ALL_GCS int AbstractAssembler::code_fill_byte() { return 0; diff -r a413bcd552a4 -r 5fc51c1ecdeb src/cpu/zero/vm/cppInterpreter_zero.cpp --- a/src/cpu/zero/vm/cppInterpreter_zero.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/cpu/zero/vm/cppInterpreter_zero.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -47,6 +47,7 @@ #include "runtime/vframeArray.hpp" #include "stack_zero.inline.hpp" #include "utilities/debug.hpp" +#include "utilities/macros.hpp" #ifdef SHARK #include "shark/shark_globals.hpp" #endif @@ -791,7 +792,7 @@ } address InterpreterGenerator::generate_Reference_get_entry(void) { -#ifndef SERIALGC +#if INCLUDE_ALL_GCS if (UseG1GC) { // We need to generate have a routine that generates code to: // * load the value in the referent field @@ -803,7 +804,7 @@ // field as live. Unimplemented(); } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS // If G1 is not enabled then attempt to go through the accessor entry point // Reference.get is an accessor diff -r a413bcd552a4 -r 5fc51c1ecdeb src/cpu/zero/vm/shark_globals_zero.hpp --- a/src/cpu/zero/vm/shark_globals_zero.hpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/cpu/zero/vm/shark_globals_zero.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. * Copyright 2008, 2009, 2010 Red Hat, Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -51,7 +51,7 @@ define_pd_global(intx, OnStackReplacePercentage, 933 ); define_pd_global(intx, FreqInlineSize, 325 ); define_pd_global(intx, InlineSmallCode, 1000 ); -define_pd_global(intx, NewRatio, 12 ); +define_pd_global(uintx, NewRatio, 12 ); define_pd_global(intx, NewSizeThreadIncrease, 4*K ); define_pd_global(intx, InitialCodeCacheSize, 160*K); define_pd_global(intx, ReservedCodeCacheSize, 32*M ); diff -r a413bcd552a4 -r 5fc51c1ecdeb src/os/bsd/vm/osThread_bsd.hpp --- a/src/os/bsd/vm/osThread_bsd.hpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/os/bsd/vm/osThread_bsd.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -49,6 +49,11 @@ // (e.g. pthread_kill). pthread_t _pthread_id; + // This is the "thread_id" from struct thread_identifier_info. According to a + // comment in thread_info.h, this is a "system-wide unique 64-bit thread id". + // The value is used by SA to correlate threads. + uint64_t _unique_thread_id; + sigset_t _caller_sigmask; // Caller's signal mask public: @@ -77,6 +82,10 @@ _pthread_id = tid; } + void set_unique_thread_id(uint64_t id) { + _unique_thread_id = id; + } + // *************************************************************** // suspension support. // *************************************************************** diff -r a413bcd552a4 -r 5fc51c1ecdeb src/os/bsd/vm/os_bsd.cpp --- a/src/os/bsd/vm/os_bsd.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/os/bsd/vm/os_bsd.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -657,6 +657,18 @@ objc_registerThreadWithCollector_t objc_registerThreadWithCollectorFunction = NULL; #endif +#ifdef __APPLE__ +static uint64_t locate_unique_thread_id() { + // Additional thread_id used to correlate threads in SA + thread_identifier_info_data_t m_ident_info; + mach_msg_type_number_t count = THREAD_IDENTIFIER_INFO_COUNT; + + thread_info(::mach_thread_self(), THREAD_IDENTIFIER_INFO, + (thread_info_t) &m_ident_info, &count); + return m_ident_info.thread_id; +} +#endif + // Thread start routine for all newly created threads static void *java_start(Thread *thread) { // Try to randomize the cache line index of hot stack frames. @@ -685,6 +697,7 @@ #ifdef __APPLE__ // thread_id is mach thread on macos osthread->set_thread_id(::mach_thread_self()); + osthread->set_unique_thread_id(locate_unique_thread_id()); #else // thread_id is pthread_id on BSD osthread->set_thread_id(::pthread_self()); @@ -847,6 +860,7 @@ // Store pthread info into the OSThread #ifdef __APPLE__ osthread->set_thread_id(::mach_thread_self()); + osthread->set_unique_thread_id(locate_unique_thread_id()); #else osthread->set_thread_id(::pthread_self()); #endif @@ -2873,7 +2887,9 @@ void signalHandler(int sig, siginfo_t* info, void* uc) { assert(info != NULL && uc != NULL, "it must be old kernel"); + int orig_errno = errno; // Preserve errno value over signal handler. JVM_handle_bsd_signal(sig, info, uc, true); + errno = orig_errno; } diff -r a413bcd552a4 -r 5fc51c1ecdeb src/os/linux/vm/os_linux.cpp --- a/src/os/linux/vm/os_linux.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/os/linux/vm/os_linux.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -1155,13 +1155,9 @@ // for initial thread if its stack size exceeds 6M. Cap it at 2M, // in case other parts in glibc still assumes 2M max stack size. // FIXME: alt signal stack is gone, maybe we can relax this constraint? -#ifndef IA64 - if (stack_size > 2 * K * K) stack_size = 2 * K * K; -#else // Problem still exists RH7.2 (IA64 anyway) but 2MB is a little small - if (stack_size > 4 * K * K) stack_size = 4 * K * K; -#endif - + if (stack_size > 2 * K * K IA64_ONLY(*2)) + stack_size = 2 * K * K IA64_ONLY(*2); // Try to figure out where the stack base (top) is. This is harder. // // When an application is started, glibc saves the initial stack pointer in @@ -3657,14 +3653,9 @@ void signalHandler(int sig, siginfo_t* info, void* uc) { assert(info != NULL && uc != NULL, "it must be old kernel"); - ResourceMark rm; - if (TraceSignals) { - tty->print_cr(err_msg("signal received: code=%d errno=%d signo=%d thread=%s address=%x", info->si_code, info->si_errno, info->si_signo, Thread::current()->name(), info->si_addr)); - } + int orig_errno = errno; // Preserve errno value over signal handler. JVM_handle_linux_signal(sig, info, uc, true); - if (TraceSignals) { - tty->print_cr("signal handled"); - } + errno = orig_errno; } @@ -4374,16 +4365,12 @@ if (is_NPTL()) { return pthread_cond_timedwait(_cond, _mutex, _abstime); } else { -#ifndef IA64 // 6292965: LinuxThreads pthread_cond_timedwait() resets FPU control // word back to default 64bit precision if condvar is signaled. Java // wants 53bit precision. Save and restore current value. int fpu = get_fpu_control_word(); -#endif // IA64 int status = pthread_cond_timedwait(_cond, _mutex, _abstime); -#ifndef IA64 set_fpu_control_word(fpu); -#endif // IA64 return status; } } @@ -4756,49 +4743,26 @@ // static jlong slow_thread_cpu_time(Thread *thread, bool user_sys_cpu_time) { - static bool proc_pid_cpu_avail = true; static bool proc_task_unchecked = true; static const char *proc_stat_path = "/proc/%d/stat"; pid_t tid = thread->osthread()->thread_id(); - int i; char *s; char stat[2048]; int statlen; char proc_name[64]; int count; long sys_time, user_time; - char string[64]; char cdummy; int idummy; long ldummy; FILE *fp; - // We first try accessing /proc//cpu since this is faster to - // process. If this file is not present (linux kernels 2.5 and above) - // then we open /proc//stat. - if ( proc_pid_cpu_avail ) { - sprintf(proc_name, "/proc/%d/cpu", tid); - fp = fopen(proc_name, "r"); - if ( fp != NULL ) { - count = fscanf( fp, "%s %lu %lu\n", string, &user_time, &sys_time); - fclose(fp); - if ( count != 3 ) return -1; - - if (user_sys_cpu_time) { - return ((jlong)sys_time + (jlong)user_time) * (1000000000 / clock_tics_per_sec); - } else { - return (jlong)user_time * (1000000000 / clock_tics_per_sec); - } - } - else proc_pid_cpu_avail = false; - } - // The /proc//stat aggregates per-process usage on // new Linux kernels 2.6+ where NPTL is supported. // The /proc/self/task//stat still has the per-thread usage. // See bug 6328462. - // There can be no directory /proc/self/task on kernels 2.4 with NPTL - // and possibly in some other cases, so we check its availability. + // There possibly can be cases where there is no directory + // /proc/self/task, so we check its availability. if (proc_task_unchecked && os::Linux::is_NPTL()) { // This is executed only once proc_task_unchecked = false; @@ -4823,7 +4787,6 @@ // We don't really need to know the command string, just find the last // occurrence of ")" and then start parsing from there. See bug 4726580. s = strrchr(stat, ')'); - i = 0; if (s == NULL ) return -1; // Skip blank chars diff -r a413bcd552a4 -r 5fc51c1ecdeb src/os/solaris/vm/os_solaris.cpp --- a/src/os/solaris/vm/os_solaris.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/os/solaris/vm/os_solaris.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -1865,7 +1865,7 @@ // Die immediately, no exit hook, no abort hook, no cleanup. void os::die() { - _exit(-1); + ::abort(); // dump core (for debugging) } // unused @@ -4317,7 +4317,9 @@ void signalHandler(int sig, siginfo_t* info, void* ucVoid) { + int orig_errno = errno; // Preserve errno value over signal handler. JVM_handle_solaris_signal(sig, info, ucVoid, true); + errno = orig_errno; } /* Do not delete - if guarantee is ever removed, a signal handler (even empty) diff -r a413bcd552a4 -r 5fc51c1ecdeb src/os/windows/vm/os_windows.cpp --- a/src/os/windows/vm/os_windows.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/os/windows/vm/os_windows.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -349,6 +349,33 @@ #ifdef _M_IA64 // IA64 has memory and register stacks + // + // This is the stack layout you get on NT/IA64 if you specify 1MB stack limit + // at thread creation (1MB backing store growing upwards, 1MB memory stack + // growing downwards, 2MB summed up) + // + // ... + // ------- top of stack (high address) ----- + // | + // | 1MB + // | Backing Store (Register Stack) + // | + // | / \ + // | | + // | | + // | | + // ------------------------ stack base ----- + // | 1MB + // | Memory Stack + // | + // | | + // | | + // | | + // | \ / + // | + // ----- bottom of stack (low address) ----- + // ... + stack_size = stack_size / 2; #endif return stack_bottom + stack_size; @@ -1913,7 +1940,7 @@ // a counter for each possible signal value, including signal_thread exit signal static volatile jint pending_signals[NSIG+1] = { 0 }; -static HANDLE sig_sem; +static HANDLE sig_sem = NULL; void os::signal_init_pd() { // Initialize signal structures @@ -1943,10 +1970,11 @@ void os::signal_notify(int signal_number) { BOOL ret; - - Atomic::inc(&pending_signals[signal_number]); - ret = ::ReleaseSemaphore(sig_sem, 1, NULL); - assert(ret != 0, "ReleaseSemaphore() failed"); + if (sig_sem != NULL) { + Atomic::inc(&pending_signals[signal_number]); + ret = ::ReleaseSemaphore(sig_sem, 1, NULL); + assert(ret != 0, "ReleaseSemaphore() failed"); + } } static int check_pending_signals(bool wait_for_signal) { @@ -2005,17 +2033,34 @@ JavaThread* thread = JavaThread::current(); // Save pc in thread #ifdef _M_IA64 - thread->set_saved_exception_pc((address)exceptionInfo->ContextRecord->StIIP); + // Do not blow up if no thread info available. + if (thread) { + // Saving PRECISE pc (with slot information) in thread. + uint64_t precise_pc = (uint64_t) exceptionInfo->ExceptionRecord->ExceptionAddress; + // Convert precise PC into "Unix" format + precise_pc = (precise_pc & 0xFFFFFFFFFFFFFFF0) | ((precise_pc & 0xF) >> 2); + thread->set_saved_exception_pc((address)precise_pc); + } // Set pc to handler exceptionInfo->ContextRecord->StIIP = (DWORD64)handler; + // Clear out psr.ri (= Restart Instruction) in order to continue + // at the beginning of the target bundle. + exceptionInfo->ContextRecord->StIPSR &= 0xFFFFF9FFFFFFFFFF; + assert(((DWORD64)handler & 0xF) == 0, "Target address must point to the beginning of a bundle!"); #elif _M_AMD64 - thread->set_saved_exception_pc((address)exceptionInfo->ContextRecord->Rip); + // Do not blow up if no thread info available. + if (thread) { + thread->set_saved_exception_pc((address)(DWORD_PTR)exceptionInfo->ContextRecord->Rip); + } // Set pc to handler exceptionInfo->ContextRecord->Rip = (DWORD64)handler; #else - thread->set_saved_exception_pc((address)exceptionInfo->ContextRecord->Eip); + // Do not blow up if no thread info available. + if (thread) { + thread->set_saved_exception_pc((address)(DWORD_PTR)exceptionInfo->ContextRecord->Eip); + } // Set pc to handler - exceptionInfo->ContextRecord->Eip = (LONG)handler; + exceptionInfo->ContextRecord->Eip = (DWORD)(DWORD_PTR)handler; #endif // Continue the execution @@ -2040,6 +2085,14 @@ // included or copied here. #define EXCEPTION_INFO_EXEC_VIOLATION 0x08 +// Handle NAT Bit consumption on IA64. +#ifdef _M_IA64 +#define EXCEPTION_REG_NAT_CONSUMPTION STATUS_REG_NAT_CONSUMPTION +#endif + +// Windows Vista/2008 heap corruption check +#define EXCEPTION_HEAP_CORRUPTION 0xC0000374 + #define def_excpt(val) #val, val struct siglabel { @@ -2082,6 +2135,10 @@ def_excpt(EXCEPTION_GUARD_PAGE), def_excpt(EXCEPTION_INVALID_HANDLE), def_excpt(EXCEPTION_UNCAUGHT_CXX_EXCEPTION), + def_excpt(EXCEPTION_HEAP_CORRUPTION), +#ifdef _M_IA64 + def_excpt(EXCEPTION_REG_NAT_CONSUMPTION), +#endif NULL, 0 }; @@ -2222,7 +2279,14 @@ if (InterceptOSException) return EXCEPTION_CONTINUE_SEARCH; DWORD exception_code = exceptionInfo->ExceptionRecord->ExceptionCode; #ifdef _M_IA64 - address pc = (address) exceptionInfo->ContextRecord->StIIP; + // On Itanium, we need the "precise pc", which has the slot number coded + // into the least 4 bits: 0000=slot0, 0100=slot1, 1000=slot2 (Windows format). + address pc = (address) exceptionInfo->ExceptionRecord->ExceptionAddress; + // Convert the pc to "Unix format", which has the slot number coded + // into the least 2 bits: 0000=slot0, 0001=slot1, 0010=slot2 + // This is needed for IA64 because "relocation" / "implicit null check" / "poll instruction" + // information is saved in the Unix format. + address pc_unix_format = (address) ((((uint64_t)pc) & 0xFFFFFFFFFFFFFFF0) | ((((uint64_t)pc) & 0xF) >> 2)); #elif _M_AMD64 address pc = (address) exceptionInfo->ContextRecord->Rip; #else @@ -2337,29 +2401,40 @@ if (exception_code == EXCEPTION_STACK_OVERFLOW) { if (os::uses_stack_guard_pages()) { #ifdef _M_IA64 - // - // If it's a legal stack address continue, Windows will map it in. - // + // Use guard page for register stack. PEXCEPTION_RECORD exceptionRecord = exceptionInfo->ExceptionRecord; address addr = (address) exceptionRecord->ExceptionInformation[1]; - if (addr > thread->stack_yellow_zone_base() && addr < thread->stack_base() ) - return EXCEPTION_CONTINUE_EXECUTION; - - // The register save area is the same size as the memory stack - // and starts at the page just above the start of the memory stack. - // If we get a fault in this area, we've run out of register - // stack. If we are in java, try throwing a stack overflow exception. - if (addr > thread->stack_base() && - addr <= (thread->stack_base()+thread->stack_size()) ) { - char buf[256]; - jio_snprintf(buf, sizeof(buf), - "Register stack overflow, addr:%p, stack_base:%p\n", - addr, thread->stack_base() ); - tty->print_raw_cr(buf); - // If not in java code, return and hope for the best. - return in_java ? Handle_Exception(exceptionInfo, - SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::STACK_OVERFLOW)) - : EXCEPTION_CONTINUE_EXECUTION; + // Check for a register stack overflow on Itanium + if (thread->addr_inside_register_stack_red_zone(addr)) { + // Fatal red zone violation happens if the Java program + // catches a StackOverflow error and does so much processing + // that it runs beyond the unprotected yellow guard zone. As + // a result, we are out of here. + fatal("ERROR: Unrecoverable stack overflow happened. JVM will exit."); + } else if(thread->addr_inside_register_stack(addr)) { + // Disable the yellow zone which sets the state that + // we've got a stack overflow problem. + if (thread->stack_yellow_zone_enabled()) { + thread->disable_stack_yellow_zone(); + } + // Give us some room to process the exception. + thread->disable_register_stack_guard(); + // Tracing with +Verbose. + if (Verbose) { + tty->print_cr("SOF Compiled Register Stack overflow at " INTPTR_FORMAT " (SIGSEGV)", pc); + tty->print_cr("Register Stack access at " INTPTR_FORMAT, addr); + tty->print_cr("Register Stack base " INTPTR_FORMAT, thread->register_stack_base()); + tty->print_cr("Register Stack [" INTPTR_FORMAT "," INTPTR_FORMAT "]", + thread->register_stack_base(), + thread->register_stack_base() + thread->stack_size()); + } + + // Reguard the permanent register stack red zone just to be sure. + // We saw Windows silently disabling this without telling us. + thread->enable_register_stack_red_zone(); + + return Handle_Exception(exceptionInfo, + SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::STACK_OVERFLOW)); } #endif if (thread->stack_yellow_zone_enabled()) { @@ -2434,50 +2509,33 @@ { // Null pointer exception. #ifdef _M_IA64 - // We catch register stack overflows in compiled code by doing - // an explicit compare and executing a st8(G0, G0) if the - // BSP enters into our guard area. We test for the overflow - // condition and fall into the normal null pointer exception - // code if BSP hasn't overflowed. - if ( in_java ) { - if(thread->register_stack_overflow()) { - assert((address)exceptionInfo->ContextRecord->IntS3 == - thread->register_stack_limit(), - "GR7 doesn't contain register_stack_limit"); - // Disable the yellow zone which sets the state that - // we've got a stack overflow problem. - if (thread->stack_yellow_zone_enabled()) { - thread->disable_stack_yellow_zone(); + // Process implicit null checks in compiled code. Note: Implicit null checks + // can happen even if "ImplicitNullChecks" is disabled, e.g. in vtable stubs. + if (CodeCache::contains((void*) pc_unix_format) && !MacroAssembler::needs_explicit_null_check((intptr_t) addr)) { + CodeBlob *cb = CodeCache::find_blob_unsafe(pc_unix_format); + // Handle implicit null check in UEP method entry + if (cb && (cb->is_frame_complete_at(pc) || + (cb->is_nmethod() && ((nmethod *)cb)->inlinecache_check_contains(pc)))) { + if (Verbose) { + intptr_t *bundle_start = (intptr_t*) ((intptr_t) pc_unix_format & 0xFFFFFFFFFFFFFFF0); + tty->print_cr("trap: null_check at " INTPTR_FORMAT " (SIGSEGV)", pc_unix_format); + tty->print_cr(" to addr " INTPTR_FORMAT, addr); + tty->print_cr(" bundle is " INTPTR_FORMAT " (high), " INTPTR_FORMAT " (low)", + *(bundle_start + 1), *bundle_start); } - // Give us some room to process the exception - thread->disable_register_stack_guard(); - // Update GR7 with the new limit so we can continue running - // compiled code. - exceptionInfo->ContextRecord->IntS3 = - (ULONGLONG)thread->register_stack_limit(); return Handle_Exception(exceptionInfo, - SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::STACK_OVERFLOW)); - } else { - // - // Check for implicit null - // We only expect null pointers in the stubs (vtable) - // the rest are checked explicitly now. - // - if (((uintptr_t)addr) < os::vm_page_size() ) { - // an access to the first page of VM--assume it is a null pointer - address stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::IMPLICIT_NULL); - if (stub != NULL) return Handle_Exception(exceptionInfo, stub); - } + SharedRuntime::continuation_for_implicit_exception(thread, pc_unix_format, SharedRuntime::IMPLICIT_NULL)); } - } // in_java - - // IA64 doesn't use implicit null checking yet. So we shouldn't - // get here. - tty->print_raw_cr("Access violation, possible null pointer exception"); + } + + // Implicit null checks were processed above. Hence, we should not reach + // here in the usual case => die! + if (Verbose) tty->print_raw_cr("Access violation, possible null pointer exception"); report_error(t, exception_code, pc, exceptionInfo->ExceptionRecord, exceptionInfo->ContextRecord); return EXCEPTION_CONTINUE_SEARCH; -#else /* !IA64 */ + +#else // !IA64 // Windows 98 reports faulting addresses incorrectly if (!MacroAssembler::needs_explicit_null_check((intptr_t)addr) || @@ -2509,7 +2567,24 @@ report_error(t, exception_code, pc, exceptionInfo->ExceptionRecord, exceptionInfo->ContextRecord); return EXCEPTION_CONTINUE_SEARCH; - } + } // /EXCEPTION_ACCESS_VIOLATION + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +#if defined _M_IA64 + else if ((exception_code == EXCEPTION_ILLEGAL_INSTRUCTION || + exception_code == EXCEPTION_ILLEGAL_INSTRUCTION_2)) { + M37 handle_wrong_method_break(0, NativeJump::HANDLE_WRONG_METHOD, PR0); + + // Compiled method patched to be non entrant? Following conditions must apply: + // 1. must be first instruction in bundle + // 2. must be a break instruction with appropriate code + if((((uint64_t) pc & 0x0F) == 0) && + (((IPF_Bundle*) pc)->get_slot0() == handle_wrong_method_break.bits())) { + return Handle_Exception(exceptionInfo, + (address)SharedRuntime::get_handle_wrong_method_stub()); + } + } // /EXCEPTION_ILLEGAL_INSTRUCTION +#endif + if (in_java) { switch (exception_code) { diff -r a413bcd552a4 -r 5fc51c1ecdeb src/os_cpu/bsd_x86/vm/globals_bsd_x86.hpp --- a/src/os_cpu/bsd_x86/vm/globals_bsd_x86.hpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/os_cpu/bsd_x86/vm/globals_bsd_x86.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -42,7 +42,7 @@ #endif // AMD64 define_pd_global(intx, CompilerThreadStackSize, 0); -define_pd_global(intx, SurvivorRatio, 8); +define_pd_global(uintx, SurvivorRatio, 8); define_pd_global(uintx, JVMInvokeMethodSlack, 8192); diff -r a413bcd552a4 -r 5fc51c1ecdeb src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp --- a/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -372,7 +372,7 @@ CAST_FROM_FN_PTR(address, os::current_frame)); if (os::is_first_C_frame(&myframe)) { // stack is not walkable - return frame(NULL, NULL, NULL); + return frame(); } else { return os::get_sender_for_C_frame(&myframe); } diff -r a413bcd552a4 -r 5fc51c1ecdeb src/os_cpu/bsd_x86/vm/vmStructs_bsd_x86.hpp --- a/src/os_cpu/bsd_x86/vm/vmStructs_bsd_x86.hpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/os_cpu/bsd_x86/vm/vmStructs_bsd_x86.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -35,17 +35,16 @@ /* Threads (NOTE: incomplete) */ \ /******************************/ \ nonstatic_field(OSThread, _thread_id, OSThread::thread_id_t) \ - nonstatic_field(OSThread, _pthread_id, pthread_t) + nonstatic_field(OSThread, _unique_thread_id, uint64_t) #define VM_TYPES_OS_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type) \ \ /**********************/ \ - /* Posix Thread IDs */ \ + /* Thread IDs */ \ /**********************/ \ \ - declare_unsigned_integer_type(OSThread::thread_id_t) \ - declare_unsigned_integer_type(pthread_t) + declare_unsigned_integer_type(OSThread::thread_id_t) #define VM_INT_CONSTANTS_OS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) diff -r a413bcd552a4 -r 5fc51c1ecdeb src/os_cpu/linux_x86/vm/os_linux_x86.cpp --- a/src/os_cpu/linux_x86/vm/os_linux_x86.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/os_cpu/linux_x86/vm/os_linux_x86.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -189,7 +189,7 @@ CAST_FROM_FN_PTR(address, os::current_frame)); if (os::is_first_C_frame(&myframe)) { // stack is not walkable - return frame(NULL, NULL, NULL); + return frame(); } else { return os::get_sender_for_C_frame(&myframe); } diff -r a413bcd552a4 -r 5fc51c1ecdeb src/os_cpu/windows_x86/vm/os_windows_x86.cpp --- a/src/os_cpu/windows_x86/vm/os_windows_x86.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/os_cpu/windows_x86/vm/os_windows_x86.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -399,7 +399,7 @@ typedef intptr_t* get_fp_func (); get_fp_func* func = CAST_TO_FN_PTR(get_fp_func*, StubRoutines::x86::get_previous_fp_entry()); - if (func == NULL) return frame(NULL, NULL, NULL); + if (func == NULL) return frame(); intptr_t* fp = (*func)(); #else intptr_t* fp = _get_previous_fp(); @@ -410,7 +410,7 @@ CAST_FROM_FN_PTR(address, os::current_frame)); if (os::is_first_C_frame(&myframe)) { // stack is not walkable - return frame(NULL, NULL, NULL); + return frame(); } else { return os::get_sender_for_C_frame(&myframe); } diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/tools/whitebox/sun/hotspot/WhiteBox.java --- a/src/share/tools/whitebox/sun/hotspot/WhiteBox.java Tue Mar 05 21:58:51 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,79 +0,0 @@ -/* - * Copyright (c) 2012, 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 sun.hotspot; -import java.security.BasicPermission; -import sun.hotspot.parser.DiagnosticCommand; - -public class WhiteBox { - - @SuppressWarnings("serial") - public static class WhiteBoxPermission extends BasicPermission { - public WhiteBoxPermission(String s) { - super(s); - } - } - - private WhiteBox() {} - private static final WhiteBox instance = new WhiteBox(); - private static native void registerNatives(); - - /** - * Returns the singleton WhiteBox instance. - * - * The returned WhiteBox object should be carefully guarded - * by the caller, since it can be used to read and write data - * at arbitrary memory addresses. It must never be passed to - * untrusted code. - */ - public synchronized static WhiteBox getWhiteBox() { - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - sm.checkPermission(new WhiteBoxPermission("getInstance")); - } - return instance; - } - - static { - registerNatives(); - } - - // Memory - public native long getObjectAddress(Object o); - public native int getHeapOopSize(); - - // Runtime - // Make sure class name is in the correct format - public boolean isClassAlive(String name) { - return isClassAlive0(name.replace('.', '/')); - } - private native boolean isClassAlive0(String name); - - // G1 - public native boolean g1InConcurrentMark(); - public native boolean g1IsHumongous(Object o); - public native long g1NumFreeRegions(); - public native int g1RegionSize(); - public native Object[] parseCommandLine(String commandline, DiagnosticCommand[] args); -} diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/tools/whitebox/sun/hotspot/parser/DiagnosticCommand.java --- a/src/share/tools/whitebox/sun/hotspot/parser/DiagnosticCommand.java Tue Mar 05 21:58:51 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,43 +0,0 @@ -package sun.hotspot.parser; - -public class DiagnosticCommand { - - public enum DiagnosticArgumentType { - JLONG, BOOLEAN, STRING, NANOTIME, STRINGARRAY, MEMORYSIZE - } - - private String name; - private String desc; - private DiagnosticArgumentType type; - private boolean mandatory; - private String defaultValue; - - public DiagnosticCommand(String name, String desc, DiagnosticArgumentType type, - boolean mandatory, String defaultValue) { - this.name = name; - this.desc = desc; - this.type = type; - this.mandatory = mandatory; - this.defaultValue = defaultValue; - } - - public String getName() { - return name; - } - - public String getDesc() { - return desc; - } - - public DiagnosticArgumentType getType() { - return type; - } - - public boolean isMandatory() { - return mandatory; - } - - public String getDefaultValue() { - return defaultValue; - } -} diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/adlc/adlparse.cpp --- a/src/share/vm/adlc/adlparse.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/adlc/adlparse.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -168,7 +168,7 @@ // Check for block delimiter if ( (_curchar != '%') || ( next_char(), (_curchar != '{')) ) { - parse_err(SYNERR, "missing '%{' in instruction definition\n"); + parse_err(SYNERR, "missing '%%{' in instruction definition\n"); return; } next_char(); // Maintain the invariant @@ -253,7 +253,7 @@ } while(_curchar != '%'); next_char(); if (_curchar != '}') { - parse_err(SYNERR, "missing '%}' in instruction definition\n"); + parse_err(SYNERR, "missing '%%}' in instruction definition\n"); return; } // Check for "Set" form of chain rule @@ -423,7 +423,7 @@ skipws(); // Check for block delimiter if ((_curchar != '%') || (*(_ptr+1) != '{')) { // If not open block - parse_err(SYNERR, "missing '%c{' in operand definition\n","%"); + parse_err(SYNERR, "missing '%%{' in operand definition\n"); return; } next_char(); next_char(); // Skip over "%{" symbol @@ -483,7 +483,7 @@ } while(_curchar != '%'); next_char(); if (_curchar != '}') { - parse_err(SYNERR, "missing '%}' in operand definition\n"); + parse_err(SYNERR, "missing '%%}' in operand definition\n"); return; } // Add operand to tail of operand list @@ -1324,7 +1324,7 @@ // Check for block delimiter if ( (_curchar != '%') || ( next_char(), (_curchar != '{')) ) { - parse_err(SYNERR, "missing '%{' in pipeline definition\n"); + parse_err(SYNERR, "missing '%%{' in pipeline definition\n"); return; } next_char(); // Maintain the invariant @@ -1341,7 +1341,7 @@ skipws(); if ( (_curchar != '%') || ( next_char(), (_curchar != '{')) ) { - parse_err(SYNERR, "expected '%{'\n"); + parse_err(SYNERR, "expected '%%{'\n"); return; } next_char(); skipws(); @@ -1397,7 +1397,7 @@ skipws(); if ( (_curchar != '%') || ( next_char(), (_curchar != '{')) ) { - parse_err(SYNERR, "expected '%{'\n"); + parse_err(SYNERR, "expected '%%{'\n"); return; } next_char(); skipws(); @@ -1586,7 +1586,7 @@ if ( (_curchar != '%') || ( next_char(), (_curchar != '}')) ) { - parse_err(SYNERR, "expected '%}', found \"%c\"\n", _curchar); + parse_err(SYNERR, "expected '%%}', found \"%c\"\n", _curchar); } next_char(); skipws(); @@ -1612,7 +1612,7 @@ next_char(); if (_curchar != '}') { - parse_err(SYNERR, "missing \"%}\" in pipeline definition\n"); + parse_err(SYNERR, "missing \"%%}\" in pipeline definition\n"); return; } @@ -1775,7 +1775,7 @@ // Check for block delimiter if ( (_curchar != '%') || ( next_char(), (_curchar != '{')) ) { - parse_err(SYNERR, "missing \"%{\" in pipe_class definition\n"); + parse_err(SYNERR, "missing \"%%{\" in pipe_class definition\n"); return; } next_char(); @@ -2062,7 +2062,7 @@ next_char(); if (_curchar != '}') { - parse_err(SYNERR, "missing \"%}\" in pipe_class definition\n"); + parse_err(SYNERR, "missing \"%%}\" in pipe_class definition\n"); return; } @@ -3341,12 +3341,12 @@ char *disp = NULL; if (_curchar != '%') { - parse_err(SYNERR, "Missing '%{' for 'interface' block.\n"); + parse_err(SYNERR, "Missing '%%{' for 'interface' block.\n"); return NULL; } next_char(); // Skip '%' if (_curchar != '{') { - parse_err(SYNERR, "Missing '%{' for 'interface' block.\n"); + parse_err(SYNERR, "Missing '%%{' for 'interface' block.\n"); return NULL; } next_char(); // Skip '{' @@ -3354,7 +3354,7 @@ do { char *field = get_ident(); if (field == NULL) { - parse_err(SYNERR, "Expected keyword, base|index|scale|disp, or '%}' ending interface.\n"); + parse_err(SYNERR, "Expected keyword, base|index|scale|disp, or '%%}' ending interface.\n"); return NULL; } if ( strcmp(field,"base") == 0 ) { @@ -3370,13 +3370,13 @@ disp = interface_field_parse(); } else { - parse_err(SYNERR, "Expected keyword, base|index|scale|disp, or '%}' ending interface.\n"); + parse_err(SYNERR, "Expected keyword, base|index|scale|disp, or '%%}' ending interface.\n"); return NULL; } } while( _curchar != '%' ); next_char(); // Skip '%' if ( _curchar != '}' ) { - parse_err(SYNERR, "Missing '%}' for 'interface' block.\n"); + parse_err(SYNERR, "Missing '%%}' for 'interface' block.\n"); return NULL; } next_char(); // Skip '}' @@ -3403,12 +3403,12 @@ const char *greater_format = "gt"; if (_curchar != '%') { - parse_err(SYNERR, "Missing '%{' for 'cond_interface' block.\n"); + parse_err(SYNERR, "Missing '%%{' for 'cond_interface' block.\n"); return NULL; } next_char(); // Skip '%' if (_curchar != '{') { - parse_err(SYNERR, "Missing '%{' for 'cond_interface' block.\n"); + parse_err(SYNERR, "Missing '%%{' for 'cond_interface' block.\n"); return NULL; } next_char(); // Skip '{' @@ -3416,7 +3416,7 @@ do { char *field = get_ident(); if (field == NULL) { - parse_err(SYNERR, "Expected keyword, base|index|scale|disp, or '%}' ending interface.\n"); + parse_err(SYNERR, "Expected keyword, base|index|scale|disp, or '%%}' ending interface.\n"); return NULL; } if ( strcmp(field,"equal") == 0 ) { @@ -3438,13 +3438,13 @@ greater = interface_field_parse(&greater_format); } else { - parse_err(SYNERR, "Expected keyword, base|index|scale|disp, or '%}' ending interface.\n"); + parse_err(SYNERR, "Expected keyword, base|index|scale|disp, or '%%}' ending interface.\n"); return NULL; } } while( _curchar != '%' ); next_char(); // Skip '%' if ( _curchar != '}' ) { - parse_err(SYNERR, "Missing '%}' for 'interface' block.\n"); + parse_err(SYNERR, "Missing '%%}' for 'interface' block.\n"); return NULL; } next_char(); // Skip '}' @@ -3543,7 +3543,7 @@ } else if ((cnstr = find_cpp_block("match constructor")) == NULL ) { parse_err(SYNERR, "invalid construction of match rule\n" - "Missing ';' or invalid '%{' and '%}' constructor\n"); + "Missing ';' or invalid '%%{' and '%%}' constructor\n"); return NULL; // No MatchRule to return } if (_AD._adl_debug > 1) @@ -3646,7 +3646,7 @@ // Check for closing '"' and '%}' in format description skipws(); // Move to closing '%}' if ( _curchar != '%' ) { - parse_err(SYNERR, "non-blank characters between closing '\"' and '%' in format"); + parse_err(SYNERR, "non-blank characters between closing '\"' and '%%' in format"); return NULL; } } // Done with format description inside @@ -3654,7 +3654,7 @@ skipws(); // Past format description, at '%' if ( _curchar != '%' || *(_ptr+1) != '}' ) { - parse_err(SYNERR, "missing '%}' at end of format block"); + parse_err(SYNERR, "missing '%%}' at end of format block"); return NULL; } next_char(); // Move past the '%' @@ -3785,7 +3785,7 @@ skipws(); // Past format description, at '%' if ( _curchar != '%' || *(_ptr+1) != '}' ) { - parse_err(SYNERR, "missing '%}' at end of format block"); + parse_err(SYNERR, "missing '%%}' at end of format block"); return NULL; } next_char(); // Move past the '%' @@ -3834,7 +3834,7 @@ skipws(); // Skip leading whitespace if ((_curchar != '%') || (next_char(), (_curchar != '{')) ) { // If not open block - parse_err(SYNERR, "missing '%{' in expand definition\n"); + parse_err(SYNERR, "missing '%%{' in expand definition\n"); return(NULL); } next_char(); // Maintain the invariant @@ -3933,7 +3933,7 @@ } while(_curchar != '%'); next_char(); if (_curchar != '}') { - parse_err(SYNERR, "missing '%}' in expand rule definition\n"); + parse_err(SYNERR, "missing '%%}' in expand rule definition\n"); return(NULL); } next_char(); diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/adlc/formssel.cpp --- a/src/share/vm/adlc/formssel.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/adlc/formssel.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -753,10 +753,11 @@ !strcmp(_matrule->_rChild->_opType,"DecodeNKlass") || !strcmp(_matrule->_rChild->_opType,"EncodePKlass") || !strcmp(_matrule->_rChild->_opType,"LoadN") || - !strcmp(_matrule->_rChild->_opType,"GetAndSetN") || !strcmp(_matrule->_rChild->_opType,"LoadNKlass") || !strcmp(_matrule->_rChild->_opType,"CreateEx") || // type of exception - !strcmp(_matrule->_rChild->_opType,"CheckCastPP")) ) return true; + !strcmp(_matrule->_rChild->_opType,"CheckCastPP") || + !strcmp(_matrule->_rChild->_opType,"GetAndSetP") || + !strcmp(_matrule->_rChild->_opType,"GetAndSetN")) ) return true; else if ( is_ideal_load() == Form::idealP ) return true; else if ( is_ideal_store() != Form::none ) return true; diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/asm/macroAssembler.hpp --- a/src/share/vm/asm/macroAssembler.hpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/asm/macroAssembler.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -37,10 +37,10 @@ # include "assembler_zero.hpp" #endif #ifdef TARGET_ARCH_arm -# include "assembler_arm.hpp" +# include "macroAssembler_arm.hpp" #endif #ifdef TARGET_ARCH_ppc -# include "assembler_ppc.hpp" +# include "macroAssembler_ppc.hpp" #endif #endif // SHARE_VM_ASM_MACROASSEMBLER_HPP diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/asm/macroAssembler.inline.hpp --- a/src/share/vm/asm/macroAssembler.inline.hpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/asm/macroAssembler.inline.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -37,10 +37,10 @@ # include "assembler_zero.inline.hpp" #endif #ifdef TARGET_ARCH_arm -# include "assembler_arm.inline.hpp" +# include "macroAssembler_arm.inline.hpp" #endif #ifdef TARGET_ARCH_ppc -# include "assembler_ppc.inline.hpp" +# include "macroAssembler_ppc.inline.hpp" #endif #endif // SHARE_VM_ASM_MACROASSEMBLER_INLINE_HPP diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/c1/c1_CodeStubs.hpp --- a/src/share/vm/c1/c1_CodeStubs.hpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/c1/c1_CodeStubs.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -31,6 +31,7 @@ #include "c1/c1_LIR.hpp" #include "c1/c1_Runtime1.hpp" #include "utilities/array.hpp" +#include "utilities/macros.hpp" class CodeEmitInfo; class LIR_Assembler; @@ -515,7 +516,7 @@ }; ////////////////////////////////////////////////////////////////////////////////////////// -#ifndef SERIALGC +#if INCLUDE_ALL_GCS // Code stubs for Garbage-First barriers. class G1PreBarrierStub: public CodeStub { @@ -608,7 +609,7 @@ #endif // PRODUCT }; -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS ////////////////////////////////////////////////////////////////////////////////////////// #endif // SHARE_VM_C1_C1_CODESTUBS_HPP diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/c1/c1_GraphBuilder.cpp --- a/src/share/vm/c1/c1_GraphBuilder.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/c1/c1_GraphBuilder.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -3667,11 +3667,12 @@ } // now perform tests that are based on flag settings - if (callee->force_inline() || callee->should_inline()) { - // ignore heuristic controls on inlining - if (callee->force_inline()) - print_inlining(callee, "force inline by annotation"); + if (callee->force_inline()) { + print_inlining(callee, "force inline by annotation"); + } else if (callee->should_inline()) { + print_inlining(callee, "force inline by CompileOracle"); } else { + // use heuristic controls on inlining if (inline_level() > MaxInlineLevel ) INLINE_BAILOUT("inlining too deep"); if (recursive_inline_level(callee) > MaxRecursiveInlineLevel) INLINE_BAILOUT("recursive inlining too deep"); if (callee->code_size_for_inlining() > max_inline_size() ) INLINE_BAILOUT("callee is too large"); diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/c1/c1_Instruction.cpp --- a/src/share/vm/c1/c1_Instruction.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/c1/c1_Instruction.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -188,7 +188,7 @@ ciType* LoadIndexed::declared_type() const { ciType* array_type = array()->declared_type(); - if (array_type == NULL) { + if (array_type == NULL || !array_type->is_loaded()) { return NULL; } assert(array_type->is_array_klass(), "what else?"); diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/c1/c1_LIR.cpp --- a/src/share/vm/c1/c1_LIR.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/c1/c1_LIR.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -814,7 +814,7 @@ // only visit register parameters int n = opJavaCall->_arguments->length(); - for (int i = 0; i < n; i++) { + for (int i = opJavaCall->_receiver->is_valid() ? 1 : 0; i < n; i++) { if (!opJavaCall->_arguments->at(i)->is_pointer()) { do_input(*opJavaCall->_arguments->adr_at(i)); } diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/c1/c1_LIRGenerator.cpp --- a/src/share/vm/c1/c1_LIRGenerator.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/c1/c1_LIRGenerator.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -35,9 +35,10 @@ #include "runtime/sharedRuntime.hpp" #include "runtime/stubRoutines.hpp" #include "utilities/bitMap.inline.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/g1/heapRegion.hpp" -#endif +#endif // INCLUDE_ALL_GCS #ifdef ASSERT #define __ gen()->lir(__FILE__, __LINE__)-> @@ -1417,12 +1418,12 @@ bool do_load, bool patch, CodeEmitInfo* info) { // Do the pre-write barrier, if any. switch (_bs->kind()) { -#ifndef SERIALGC +#if INCLUDE_ALL_GCS case BarrierSet::G1SATBCT: case BarrierSet::G1SATBCTLogging: G1SATBCardTableModRef_pre_barrier(addr_opr, pre_val, do_load, patch, info); break; -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS case BarrierSet::CardTableModRef: case BarrierSet::CardTableExtension: // No pre barriers @@ -1439,12 +1440,12 @@ void LIRGenerator::post_barrier(LIR_OprDesc* addr, LIR_OprDesc* new_val) { switch (_bs->kind()) { -#ifndef SERIALGC +#if INCLUDE_ALL_GCS case BarrierSet::G1SATBCT: case BarrierSet::G1SATBCTLogging: G1SATBCardTableModRef_post_barrier(addr, new_val); break; -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS case BarrierSet::CardTableModRef: case BarrierSet::CardTableExtension: CardTableModRef_post_barrier(addr, new_val); @@ -1459,7 +1460,7 @@ } //////////////////////////////////////////////////////////////////////// -#ifndef SERIALGC +#if INCLUDE_ALL_GCS void LIRGenerator::G1SATBCardTableModRef_pre_barrier(LIR_Opr addr_opr, LIR_Opr pre_val, bool do_load, bool patch, CodeEmitInfo* info) { @@ -1575,7 +1576,7 @@ __ branch_destination(slow->continuation()); } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS //////////////////////////////////////////////////////////////////////// void LIRGenerator::CardTableModRef_post_barrier(LIR_OprDesc* addr, LIR_OprDesc* new_val) { @@ -2181,7 +2182,7 @@ get_Object_unsafe(value, src.result(), off.result(), type, x->is_volatile()); -#ifndef SERIALGC +#if INCLUDE_ALL_GCS // We might be reading the value of the referent field of a // Reference object in order to attach it back to the live // object graph. If G1 is enabled then we need to record @@ -2311,7 +2312,7 @@ __ branch_destination(Lcont->label()); } } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS if (x->is_volatile() && os::is_MP()) __ membar_acquire(); } diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/ci/ciEnv.cpp --- a/src/share/vm/ci/ciEnv.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/ci/ciEnv.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -52,6 +52,7 @@ #include "runtime/reflection.hpp" #include "runtime/sharedRuntime.hpp" #include "utilities/dtrace.hpp" +#include "utilities/macros.hpp" #ifdef COMPILER1 #include "c1/c1_Runtime1.hpp" #endif @@ -596,10 +597,6 @@ assert (klass->is_instance_klass() || klass->is_array_klass(), "must be an instance or array klass "); return ciConstant(T_OBJECT, klass->java_mirror()); - } else if (tag.is_object()) { - oop obj = cpool->object_at(index); - ciObject* ciobj = get_object(obj); - return ciConstant(T_OBJECT, ciobj); } else if (tag.is_method_type()) { // must execute Java code to link this CP entry into cache[i].f1 ciSymbol* signature = get_symbol(cpool->method_type_signature_at(index)); @@ -1168,7 +1165,7 @@ void ciEnv::dump_replay_data(outputStream* out) { ASSERT_IN_VM; - + ResourceMark rm; #if INCLUDE_JVMTI out->print_cr("JvmtiExport can_access_local_variables %d", _jvmti_can_access_local_variables); out->print_cr("JvmtiExport can_hotswap_or_post_breakpoint %d", _jvmti_can_hotswap_or_post_breakpoint); diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/ci/ciInstanceKlass.cpp --- a/src/share/vm/ci/ciInstanceKlass.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/ci/ciInstanceKlass.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -580,6 +580,7 @@ } void do_field(fieldDescriptor* fd) { if (fd->is_final() && !fd->has_initial_value()) { + ResourceMark rm; oop mirror = fd->field_holder()->java_mirror(); _out->print("staticfield %s %s %s ", _holder, fd->name()->as_quoted_ascii(), fd->signature()->as_quoted_ascii()); switch (fd->field_type()) { @@ -643,6 +644,8 @@ void ciInstanceKlass::dump_replay_data(outputStream* out) { ASSERT_IN_VM; + ResourceMark rm; + InstanceKlass* ik = get_instanceKlass(); ConstantPool* cp = ik->constants(); diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/ci/ciMethod.cpp --- a/src/share/vm/ci/ciMethod.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/ci/ciMethod.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -977,7 +977,7 @@ // ciMethod::set_not_compilable // // Tell the VM that this method cannot be compiled at all. -void ciMethod::set_not_compilable() { +void ciMethod::set_not_compilable(const char* reason) { check_is_loaded(); VM_ENTRY_MARK; ciEnv* env = CURRENT_ENV; @@ -986,7 +986,7 @@ } else { _is_c2_compilable = false; } - get_Method()->set_not_compilable(env->comp_level()); + get_Method()->set_not_compilable(env->comp_level(), true, reason); } // ------------------------------------------------------------------ @@ -1178,6 +1178,7 @@ void ciMethod::dump_replay_data(outputStream* st) { ASSERT_IN_VM; + ResourceMark rm; Method* method = get_Method(); Klass* holder = method->method_holder(); st->print_cr("ciMethod %s %s %s %d %d %d %d %d", diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/ci/ciMethod.hpp --- a/src/share/vm/ci/ciMethod.hpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/ci/ciMethod.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -252,7 +252,7 @@ bool has_option(const char *option); bool can_be_compiled(); bool can_be_osr_compiled(int entry_bci); - void set_not_compilable(); + void set_not_compilable(const char* reason = NULL); bool has_compiled_code(); void log_nmethod_identity(xmlStream* log); bool is_not_reached(int bci); diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/ci/ciMethodData.cpp --- a/src/share/vm/ci/ciMethodData.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/ci/ciMethodData.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -374,6 +374,7 @@ void ciMethodData::dump_replay_data(outputStream* out) { ASSERT_IN_VM; + ResourceMark rm; MethodData* mdo = get_MethodData(); Method* method = mdo->method(); Klass* holder = method->method_holder(); diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/ci/ciReplay.cpp --- a/src/share/vm/ci/ciReplay.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/ci/ciReplay.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -30,6 +30,7 @@ #include "memory/oopFactory.hpp" #include "memory/resourceArea.hpp" #include "utilities/copy.hpp" +#include "utilities/macros.hpp" #ifndef PRODUCT diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/classfile/classFileParser.cpp --- a/src/share/vm/classfile/classFileParser.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/classfile/classFileParser.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -1856,6 +1856,154 @@ #define MAX_CODE_SIZE 65535 #define INITIAL_MAX_LVT_NUMBER 256 +/* Copy class file LVT's/LVTT's into the HotSpot internal LVT. + * + * Rules for LVT's and LVTT's are: + * - There can be any number of LVT's and LVTT's. + * - If there are n LVT's, it is the same as if there was just + * one LVT containing all the entries from the n LVT's. + * - There may be no more than one LVT entry per local variable. + * Two LVT entries are 'equal' if these fields are the same: + * start_pc, length, name, slot + * - There may be no more than one LVTT entry per each LVT entry. + * Each LVTT entry has to match some LVT entry. + * - HotSpot internal LVT keeps natural ordering of class file LVT entries. + */ +void ClassFileParser::copy_localvariable_table(ConstMethod* cm, + int lvt_cnt, + u2* localvariable_table_length, + u2** localvariable_table_start, + int lvtt_cnt, + u2* localvariable_type_table_length, + u2** localvariable_type_table_start, + TRAPS) { + + LVT_Hash** lvt_Hash = NEW_RESOURCE_ARRAY(LVT_Hash*, HASH_ROW_SIZE); + initialize_hashtable(lvt_Hash); + + // To fill LocalVariableTable in + Classfile_LVT_Element* cf_lvt; + LocalVariableTableElement* lvt = cm->localvariable_table_start(); + + for (int tbl_no = 0; tbl_no < lvt_cnt; tbl_no++) { + cf_lvt = (Classfile_LVT_Element *) localvariable_table_start[tbl_no]; + for (int idx = 0; idx < localvariable_table_length[tbl_no]; idx++, lvt++) { + copy_lvt_element(&cf_lvt[idx], lvt); + // If no duplicates, add LVT elem in hashtable lvt_Hash. + if (LVT_put_after_lookup(lvt, lvt_Hash) == false + && _need_verify + && _major_version >= JAVA_1_5_VERSION) { + clear_hashtable(lvt_Hash); + ConstantPool* cp = cm->constants(); + classfile_parse_error("Duplicated LocalVariableTable attribute " + "entry for '%s' in class file %s", + cp->symbol_at(lvt->name_cp_index)->as_utf8(), + CHECK); + } + } + } + + // To merge LocalVariableTable and LocalVariableTypeTable + Classfile_LVT_Element* cf_lvtt; + LocalVariableTableElement lvtt_elem; + + for (int tbl_no = 0; tbl_no < lvtt_cnt; tbl_no++) { + cf_lvtt = (Classfile_LVT_Element *) localvariable_type_table_start[tbl_no]; + for (int idx = 0; idx < localvariable_type_table_length[tbl_no]; idx++) { + copy_lvt_element(&cf_lvtt[idx], &lvtt_elem); + int index = hash(&lvtt_elem); + LVT_Hash* entry = LVT_lookup(&lvtt_elem, index, lvt_Hash); + if (entry == NULL) { + if (_need_verify) { + clear_hashtable(lvt_Hash); + ConstantPool* cp = cm->constants(); + classfile_parse_error("LVTT entry for '%s' in class file %s " + "does not match any LVT entry", + cp->symbol_at(lvtt_elem.name_cp_index)->as_utf8(), + CHECK); + } + } else if (entry->_elem->signature_cp_index != 0 && _need_verify) { + clear_hashtable(lvt_Hash); + ConstantPool* cp = cm->constants(); + classfile_parse_error("Duplicated LocalVariableTypeTable attribute " + "entry for '%s' in class file %s", + cp->symbol_at(lvtt_elem.name_cp_index)->as_utf8(), + CHECK); + } else { + // to add generic signatures into LocalVariableTable + entry->_elem->signature_cp_index = lvtt_elem.descriptor_cp_index; + } + } + } + clear_hashtable(lvt_Hash); +} + + +void ClassFileParser::copy_method_annotations(ClassLoaderData* loader_data, + ConstMethod* cm, + u1* runtime_visible_annotations, + int runtime_visible_annotations_length, + u1* runtime_invisible_annotations, + int runtime_invisible_annotations_length, + u1* runtime_visible_parameter_annotations, + int runtime_visible_parameter_annotations_length, + u1* runtime_invisible_parameter_annotations, + int runtime_invisible_parameter_annotations_length, + u1* runtime_visible_type_annotations, + int runtime_visible_type_annotations_length, + u1* runtime_invisible_type_annotations, + int runtime_invisible_type_annotations_length, + u1* annotation_default, + int annotation_default_length, + TRAPS) { + + AnnotationArray* a; + + if (runtime_visible_annotations_length + + runtime_invisible_annotations_length > 0) { + a = assemble_annotations(loader_data, + runtime_visible_annotations, + runtime_visible_annotations_length, + runtime_invisible_annotations, + runtime_invisible_annotations_length, + CHECK); + cm->set_method_annotations(a); + } + + if (runtime_visible_parameter_annotations_length + + runtime_invisible_parameter_annotations_length > 0) { + a = assemble_annotations(loader_data, + runtime_visible_parameter_annotations, + runtime_visible_parameter_annotations_length, + runtime_invisible_parameter_annotations, + runtime_invisible_parameter_annotations_length, + CHECK); + cm->set_parameter_annotations(a); + } + + if (annotation_default_length > 0) { + a = assemble_annotations(loader_data, + annotation_default, + annotation_default_length, + NULL, + 0, + CHECK); + cm->set_default_annotations(a); + } + + if (runtime_visible_type_annotations_length + + runtime_invisible_type_annotations_length > 0) { + a = assemble_annotations(loader_data, + runtime_visible_type_annotations, + runtime_visible_type_annotations_length, + runtime_invisible_type_annotations, + runtime_invisible_type_annotations_length, + CHECK); + cm->set_type_annotations(a); + } +} + + // Note: the parse_method below is big and clunky because all parsing of the code and exceptions // attribute is inlined. This is cumbersome to avoid since we inline most of the parts in the // Method* to save footprint, so we only know the size of the resulting Method* when the @@ -1869,10 +2017,6 @@ constantPoolHandle cp, bool is_interface, AccessFlags *promoted_flags, - AnnotationArray** method_annotations, - AnnotationArray** method_parameter_annotations, - AnnotationArray** method_default_annotations, - AnnotationArray** method_type_annotations, TRAPS) { ClassFileStream* cfs = stream(); methodHandle nullHandle; @@ -1947,6 +2091,8 @@ u2** localvariable_type_table_start; u2 method_parameters_length = 0; u1* method_parameters_data = NULL; + bool method_parameters_seen = false; + bool method_parameters_four_byte_flags; bool parsed_code_attribute = false; bool parsed_checked_exceptions_attribute = false; bool parsed_stackmap_attribute = false; @@ -2157,21 +2303,31 @@ method_attribute_length, cp, CHECK_(nullHandle)); } else if (method_attribute_name == vmSymbols::tag_method_parameters()) { + // reject multiple method parameters + if (method_parameters_seen) { + classfile_parse_error("Multiple MethodParameters attributes in class file %s", CHECK_(nullHandle)); + } + method_parameters_seen = true; method_parameters_length = cfs->get_u1_fast(); // Track the actual size (note: this is written for clarity; a // decent compiler will CSE and constant-fold this into a single // expression) - u2 actual_size = 1; + // Use the attribute length to figure out the size of flags + if (method_attribute_length == (method_parameters_length * 6u) + 1u) { + method_parameters_four_byte_flags = true; + } else if (method_attribute_length == (method_parameters_length * 4u) + 1u) { + method_parameters_four_byte_flags = false; + } else { + classfile_parse_error( + "Invalid MethodParameters method attribute length %u in class file", + method_attribute_length, CHECK_(nullHandle)); + } method_parameters_data = cfs->get_u1_buffer(); - actual_size += 2 * method_parameters_length; cfs->skip_u2_fast(method_parameters_length); - actual_size += 4 * method_parameters_length; - cfs->skip_u4_fast(method_parameters_length); - // Enforce attribute length - if (method_attribute_length != actual_size) { - classfile_parse_error( - "Invalid MethodParameters method attribute length %u in class file %s", - method_attribute_length, CHECK_(nullHandle)); + if (method_parameters_four_byte_flags) { + cfs->skip_u4_fast(method_parameters_length); + } else { + cfs->skip_u2_fast(method_parameters_length); } // ignore this attribute if it cannot be reflected if (!SystemDictionary::Parameter_klass_loaded()) @@ -2261,10 +2417,24 @@ } // All sizing information for a Method* is finally available, now create it + InlineTableSizes sizes( + total_lvt_length, + linenumber_table_length, + exception_table_length, + checked_exceptions_length, + method_parameters_length, + generic_signature_index, + runtime_visible_annotations_length + + runtime_invisible_annotations_length, + runtime_visible_parameter_annotations_length + + runtime_invisible_parameter_annotations_length, + runtime_visible_type_annotations_length + + runtime_invisible_type_annotations_length, + annotation_default_length, + 0); + Method* m = Method::allocate( - loader_data, code_length, access_flags, linenumber_table_length, - total_lvt_length, exception_table_length, checked_exceptions_length, - method_parameters_length, generic_signature_index, + loader_data, code_length, access_flags, &sizes, ConstMethod::NORMAL, CHECK_(nullHandle)); ClassLoadingService::add_class_method_size(m->size()*HeapWordSize); @@ -2316,15 +2486,16 @@ // Copy method parameters if (method_parameters_length > 0) { MethodParametersElement* elem = m->constMethod()->method_parameters_start(); - for(int i = 0; i < method_parameters_length; i++) { - elem[i].name_cp_index = - Bytes::get_Java_u2(method_parameters_data); + for (int i = 0; i < method_parameters_length; i++) { + elem[i].name_cp_index = Bytes::get_Java_u2(method_parameters_data); method_parameters_data += 2; - u4 flags = Bytes::get_Java_u4(method_parameters_data); - // This caused an alignment fault on Sparc, if flags was a u4 - elem[i].flags_lo = extract_low_short_from_int(flags); - elem[i].flags_hi = extract_high_short_from_int(flags); - method_parameters_data += 4; + if (method_parameters_four_byte_flags) { + elem[i].flags = Bytes::get_Java_u4(method_parameters_data); + method_parameters_data += 4; + } else { + elem[i].flags = Bytes::get_Java_u2(method_parameters_data); + method_parameters_data += 2; + } } } @@ -2334,107 +2505,37 @@ copy_u2_with_conversion((u2*) m->checked_exceptions_start(), checked_exceptions_start, size); } - /* Copy class file LVT's/LVTT's into the HotSpot internal LVT. - * - * Rules for LVT's and LVTT's are: - * - There can be any number of LVT's and LVTT's. - * - If there are n LVT's, it is the same as if there was just - * one LVT containing all the entries from the n LVT's. - * - There may be no more than one LVT entry per local variable. - * Two LVT entries are 'equal' if these fields are the same: - * start_pc, length, name, slot - * - There may be no more than one LVTT entry per each LVT entry. - * Each LVTT entry has to match some LVT entry. - * - HotSpot internal LVT keeps natural ordering of class file LVT entries. - */ + // Copy class file LVT's/LVTT's into the HotSpot internal LVT. if (total_lvt_length > 0) { - int tbl_no, idx; - promoted_flags->set_has_localvariable_table(); - - LVT_Hash** lvt_Hash = NEW_RESOURCE_ARRAY(LVT_Hash*, HASH_ROW_SIZE); - initialize_hashtable(lvt_Hash); - - // To fill LocalVariableTable in - Classfile_LVT_Element* cf_lvt; - LocalVariableTableElement* lvt = m->localvariable_table_start(); - - for (tbl_no = 0; tbl_no < lvt_cnt; tbl_no++) { - cf_lvt = (Classfile_LVT_Element *) localvariable_table_start[tbl_no]; - for (idx = 0; idx < localvariable_table_length[tbl_no]; idx++, lvt++) { - copy_lvt_element(&cf_lvt[idx], lvt); - // If no duplicates, add LVT elem in hashtable lvt_Hash. - if (LVT_put_after_lookup(lvt, lvt_Hash) == false - && _need_verify - && _major_version >= JAVA_1_5_VERSION ) { - clear_hashtable(lvt_Hash); - classfile_parse_error("Duplicated LocalVariableTable attribute " - "entry for '%s' in class file %s", - cp->symbol_at(lvt->name_cp_index)->as_utf8(), - CHECK_(nullHandle)); - } - } - } - - // To merge LocalVariableTable and LocalVariableTypeTable - Classfile_LVT_Element* cf_lvtt; - LocalVariableTableElement lvtt_elem; - - for (tbl_no = 0; tbl_no < lvtt_cnt; tbl_no++) { - cf_lvtt = (Classfile_LVT_Element *) localvariable_type_table_start[tbl_no]; - for (idx = 0; idx < localvariable_type_table_length[tbl_no]; idx++) { - copy_lvt_element(&cf_lvtt[idx], &lvtt_elem); - int index = hash(&lvtt_elem); - LVT_Hash* entry = LVT_lookup(&lvtt_elem, index, lvt_Hash); - if (entry == NULL) { - if (_need_verify) { - clear_hashtable(lvt_Hash); - classfile_parse_error("LVTT entry for '%s' in class file %s " - "does not match any LVT entry", - cp->symbol_at(lvtt_elem.name_cp_index)->as_utf8(), - CHECK_(nullHandle)); - } - } else if (entry->_elem->signature_cp_index != 0 && _need_verify) { - clear_hashtable(lvt_Hash); - classfile_parse_error("Duplicated LocalVariableTypeTable attribute " - "entry for '%s' in class file %s", - cp->symbol_at(lvtt_elem.name_cp_index)->as_utf8(), - CHECK_(nullHandle)); - } else { - // to add generic signatures into LocalVariableTable - entry->_elem->signature_cp_index = lvtt_elem.descriptor_cp_index; - } - } - } - clear_hashtable(lvt_Hash); + copy_localvariable_table(m->constMethod(), lvt_cnt, + localvariable_table_length, + localvariable_table_start, + lvtt_cnt, + localvariable_type_table_length, + localvariable_type_table_start, CHECK_NULL); } if (parsed_annotations.has_any_annotations()) parsed_annotations.apply_to(m); - *method_annotations = assemble_annotations(loader_data, - runtime_visible_annotations, - runtime_visible_annotations_length, - runtime_invisible_annotations, - runtime_invisible_annotations_length, - CHECK_(nullHandle)); - *method_parameter_annotations = assemble_annotations(loader_data, - runtime_visible_parameter_annotations, - runtime_visible_parameter_annotations_length, - runtime_invisible_parameter_annotations, - runtime_invisible_parameter_annotations_length, - CHECK_(nullHandle)); - *method_default_annotations = assemble_annotations(loader_data, - annotation_default, - annotation_default_length, - NULL, - 0, - CHECK_(nullHandle)); - *method_type_annotations = assemble_annotations(loader_data, - runtime_visible_type_annotations, - runtime_visible_type_annotations_length, - runtime_invisible_type_annotations, - runtime_invisible_type_annotations_length, - CHECK_(nullHandle)); + + // Copy annotations + copy_method_annotations(loader_data, m->constMethod(), + runtime_visible_annotations, + runtime_visible_annotations_length, + runtime_invisible_annotations, + runtime_invisible_annotations_length, + runtime_visible_parameter_annotations, + runtime_visible_parameter_annotations_length, + runtime_invisible_parameter_annotations, + runtime_invisible_parameter_annotations_length, + runtime_visible_type_annotations, + runtime_visible_type_annotations_length, + runtime_invisible_type_annotations, + runtime_invisible_type_annotations_length, + annotation_default, + annotation_default_length, + CHECK_NULL); if (name == vmSymbols::finalize_method_name() && signature == vmSymbols::void_method_signature()) { @@ -2450,6 +2551,7 @@ _has_vanilla_constructor = true; } + NOT_PRODUCT(m->verify()); return m; } @@ -2463,17 +2565,9 @@ bool is_interface, AccessFlags* promoted_flags, bool* has_final_method, - Array** methods_annotations, - Array** methods_parameter_annotations, - Array** methods_default_annotations, - Array** methods_type_annotations, bool* has_default_methods, TRAPS) { ClassFileStream* cfs = stream(); - AnnotationArray* method_annotations = NULL; - AnnotationArray* method_parameter_annotations = NULL; - AnnotationArray* method_default_annotations = NULL; - AnnotationArray* method_type_annotations = NULL; cfs->guarantee_more(2, CHECK_NULL); // length u2 length = cfs->get_u2_fast(); if (length == 0) { @@ -2487,10 +2581,6 @@ methodHandle method = parse_method(loader_data, cp, is_interface, promoted_flags, - &method_annotations, - &method_parameter_annotations, - &method_default_annotations, - &method_type_annotations, CHECK_NULL); if (method->is_final()) { @@ -2501,38 +2591,6 @@ *has_default_methods = true; } methods->at_put(index, method()); - - if (method_annotations != NULL) { - if (*methods_annotations == NULL) { - *methods_annotations = - MetadataFactory::new_array(loader_data, length, NULL, CHECK_NULL); - } - (*methods_annotations)->at_put(index, method_annotations); - } - - if (method_parameter_annotations != NULL) { - if (*methods_parameter_annotations == NULL) { - *methods_parameter_annotations = - MetadataFactory::new_array(loader_data, length, NULL, CHECK_NULL); - } - (*methods_parameter_annotations)->at_put(index, method_parameter_annotations); - } - - if (method_default_annotations != NULL) { - if (*methods_default_annotations == NULL) { - *methods_default_annotations = - MetadataFactory::new_array(loader_data, length, NULL, CHECK_NULL); - } - (*methods_default_annotations)->at_put(index, method_default_annotations); - } - - if (method_type_annotations != NULL) { - if (*methods_type_annotations == NULL) { - *methods_type_annotations = - MetadataFactory::new_array(loader_data, length, NULL, CHECK_NULL); - } - (*methods_type_annotations)->at_put(index, method_type_annotations); - } } if (_need_verify && length > 1) { @@ -2565,11 +2623,7 @@ Array* ClassFileParser::sort_methods(ClassLoaderData* loader_data, Array* methods, - Array* methods_annotations, - Array* methods_parameter_annotations, - Array* methods_default_annotations, - Array* methods_type_annotations, - TRAPS) { + TRAPS) { int length = methods->length(); // If JVMTI original method ordering or sharing is enabled we have to // remember the original class file ordering. @@ -2585,10 +2639,7 @@ } // Sort method array by ascending method name (for faster lookups & vtable construction) // Note that the ordering is not alphabetical, see Symbol::fast_compare - Method::sort_methods(methods, methods_annotations, - methods_parameter_annotations, - methods_default_annotations, - methods_type_annotations); + Method::sort_methods(methods); // If JVMTI original method ordering or sharing is enabled construct int // array remembering the original ordering @@ -3035,9 +3086,6 @@ k->set_source_debug_extension(_sde_buffer, _sde_length); } k->set_inner_classes(_inner_classes); - if (_annotations != NULL) { - k->annotations()->set_class_annotations(_annotations); - } } AnnotationArray* ClassFileParser::assemble_annotations(ClassLoaderData* loader_data, @@ -3348,19 +3396,10 @@ bool has_final_method = false; AccessFlags promoted_flags; promoted_flags.set_flags(0); - - Array* methods_annotations = NULL; - Array* methods_parameter_annotations = NULL; - Array* methods_default_annotations = NULL; - Array* methods_type_annotations = NULL; Array* methods = parse_methods(loader_data, cp, access_flags.is_interface(), &promoted_flags, &has_final_method, - &methods_annotations, - &methods_parameter_annotations, - &methods_default_annotations, - &methods_type_annotations, &has_default_methods, CHECK_(nullHandle)); @@ -3419,10 +3458,6 @@ // sort methods Array* method_ordering = sort_methods(loader_data, methods, - methods_annotations, - methods_parameter_annotations, - methods_default_annotations, - methods_type_annotations, CHECK_(nullHandle)); // promote flags from parse_methods() to the klass' flags @@ -4022,7 +4057,6 @@ const unsigned int total_oop_map_count = compute_oop_map_count(super_klass, nonstatic_oop_map_count, first_nonstatic_oop_offset); - // Compute reference type ReferenceType rt; if (super_klass() == NULL) { @@ -4044,7 +4078,7 @@ access_flags, name, super_klass(), - host_klass, + !host_klass.is_null(), CHECK_(nullHandle)); // Add all classes to our internal class loader list here, @@ -4090,31 +4124,15 @@ if (is_anonymous()) // I am well known to myself cp->klass_at_put(this_class_index, this_klass()); // eagerly resolve - // Allocate an annotation type if needed. - if (fields_annotations != NULL || - methods_annotations != NULL || - methods_parameter_annotations != NULL || - methods_default_annotations != NULL || - fields_type_annotations != NULL || - methods_type_annotations != NULL) { - Annotations* anno = Annotations::allocate(loader_data, - fields_annotations, methods_annotations, - methods_parameter_annotations, - methods_default_annotations, CHECK_(nullHandle)); - this_klass->set_annotations(anno); - } else { - this_klass->set_annotations(NULL); - } - - if (fields_type_annotations != NULL || - methods_type_annotations != NULL) { - assert(this_klass->annotations() != NULL, "annotations should have been allocated"); - Annotations* anno = Annotations::allocate(loader_data, - fields_type_annotations, - methods_type_annotations, - NULL, - NULL, CHECK_(nullHandle)); - this_klass->annotations()->set_type_annotations(anno); + // Assign allocations if needed + if (_annotations != NULL || _type_annotations != NULL || + fields_annotations != NULL || fields_type_annotations != NULL) { + Annotations* annotations = Annotations::allocate(loader_data, CHECK_NULL); + 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_klass->set_minor_version(minor_version); @@ -4140,27 +4158,8 @@ // Fill in field values obtained by parse_classfile_attributes if (parsed_annotations.has_any_annotations()) parsed_annotations.apply_to(this_klass); - - // Create annotations - if (_annotations != NULL && this_klass->annotations() == NULL) { - Annotations* anno = Annotations::allocate(loader_data, CHECK_NULL); - this_klass->set_annotations(anno); - } apply_parsed_class_attributes(this_klass); - // Create type annotations - if (_type_annotations != NULL) { - if (this_klass->annotations() == NULL) { - Annotations* anno = Annotations::allocate(loader_data, CHECK_NULL); - this_klass->set_annotations(anno); - } - if (this_klass->annotations()->type_annotations() == NULL) { - Annotations* anno = Annotations::allocate(loader_data, CHECK_NULL); - this_klass->annotations()->set_type_annotations(anno); - } - this_klass->annotations()->type_annotations()->set_class_annotations(_type_annotations); - } - // Miranda methods if ((num_miranda_methods > 0) || // if this class introduced new miranda methods or diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/classfile/classFileParser.hpp --- a/src/share/vm/classfile/classFileParser.hpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/classfile/classFileParser.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -199,29 +199,17 @@ constantPoolHandle cp, bool is_interface, AccessFlags* promoted_flags, - AnnotationArray** method_annotations, - AnnotationArray** method_parameter_annotations, - AnnotationArray** method_default_annotations, - AnnotationArray** method_type_annotations, TRAPS); Array* parse_methods(ClassLoaderData* loader_data, constantPoolHandle cp, bool is_interface, AccessFlags* promoted_flags, bool* has_final_method, - Array** methods_annotations, - Array** methods_parameter_annotations, - Array** methods_default_annotations, - Array** methods_type_annotations, bool* has_default_method, TRAPS); Array* sort_methods(ClassLoaderData* loader_data, Array* methods, - Array* methods_annotations, - Array* methods_parameter_annotations, - Array* methods_default_annotations, - Array* methods_type_annotations, - TRAPS); + TRAPS); u2* parse_exception_table(ClassLoaderData* loader_data, u4 code_length, u4 exception_table_length, constantPoolHandle cp, TRAPS); @@ -377,6 +365,32 @@ : cp->tag_at(index).is_klass_reference()); } + void copy_localvariable_table(ConstMethod* cm, int lvt_cnt, + u2* localvariable_table_length, + u2** localvariable_table_start, + int lvtt_cnt, + u2* localvariable_type_table_length, + u2** localvariable_type_table_start, + TRAPS); + + void copy_method_annotations(ClassLoaderData* loader_data, + ConstMethod* cm, + u1* runtime_visible_annotations, + int runtime_visible_annotations_length, + u1* runtime_invisible_annotations, + int runtime_invisible_annotations_length, + u1* runtime_visible_parameter_annotations, + int runtime_visible_parameter_annotations_length, + u1* runtime_invisible_parameter_annotations, + int runtime_invisible_parameter_annotations_length, + u1* runtime_visible_type_annotations, + int runtime_visible_type_annotations_length, + u1* runtime_invisible_type_annotations, + int runtime_invisible_type_annotations_length, + u1* annotation_default, + int annotation_default_length, + TRAPS); + public: // Constructor ClassFileParser(ClassFileStream* st) { set_stream(st); } diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/classfile/classLoaderData.cpp --- a/src/share/vm/classfile/classLoaderData.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/classfile/classLoaderData.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -50,11 +50,12 @@ #include "classfile/classLoaderData.hpp" #include "classfile/classLoaderData.inline.hpp" #include "classfile/javaClasses.hpp" +#include "classfile/metadataOnStackMark.hpp" #include "classfile/systemDictionary.hpp" #include "code/codeCache.hpp" #include "memory/metadataFactory.hpp" #include "memory/metaspaceShared.hpp" -#include "prims/jvmtiRedefineClasses.hpp" +#include "memory/oopFactory.hpp" #include "runtime/jniHandles.hpp" #include "runtime/mutex.hpp" #include "runtime/safepoint.hpp" @@ -723,13 +724,13 @@ } MetaspaceAux::dump(out); } +#endif // PRODUCT void ClassLoaderData::print_value_on(outputStream* out) const { if (class_loader() == NULL) { - out->print_cr("NULL class_loader"); + out->print("NULL class_loader"); } else { out->print("class loader "PTR_FORMAT, this); class_loader()->print_value_on(out); } } -#endif // PRODUCT diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/classfile/classLoaderData.hpp --- a/src/share/vm/classfile/classLoaderData.hpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/classfile/classLoaderData.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -220,7 +220,7 @@ void set_jmethod_ids(JNIMethodBlock* new_block) { _jmethod_ids = new_block; } void print_value() { print_value_on(tty); } - void print_value_on(outputStream* out) const PRODUCT_RETURN; + void print_value_on(outputStream* out) const; void dump(outputStream * const out) PRODUCT_RETURN; void verify(); const char* loader_name(); diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/classfile/defaultMethods.cpp --- a/src/share/vm/classfile/defaultMethods.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/classfile/defaultMethods.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1146,9 +1146,10 @@ address code_start = static_cast

(bytecodes->adr_at(0)); int code_length = bytecodes->length(); + InlineTableSizes sizes; Method* m = Method::allocate(cp->pool_holder()->class_loader_data(), - code_length, flags, 0, 0, 0, 0, 0, 0, + code_length, flags, &sizes, mt, CHECK_NULL); m->set_constants(NULL); // This will get filled in later @@ -1285,33 +1286,15 @@ enum { ANNOTATIONS, PARAMETERS, DEFAULTS, NUM_ARRAYS }; - Array* original_annots[NUM_ARRAYS] = { NULL }; - Array* original_methods = klass->methods(); - Annotations* annots = klass->annotations(); - if (annots != NULL) { - original_annots[ANNOTATIONS] = annots->methods_annotations(); - original_annots[PARAMETERS] = annots->methods_parameter_annotations(); - original_annots[DEFAULTS] = annots->methods_default_annotations(); - } - Array* original_ordering = klass->method_ordering(); Array* merged_ordering = Universe::the_empty_int_array(); int new_size = klass->methods()->length() + new_methods->length(); - Array* merged_annots[NUM_ARRAYS]; - Array* merged_methods = MetadataFactory::new_array( klass->class_loader_data(), new_size, NULL, CHECK); - for (int i = 0; i < NUM_ARRAYS; ++i) { - if (original_annots[i] != NULL) { - merged_annots[i] = MetadataFactory::new_array( - klass->class_loader_data(), new_size, CHECK); - } else { - merged_annots[i] = NULL; - } - } + if (original_ordering != NULL && original_ordering->length() > 0) { merged_ordering = MetadataFactory::new_array( klass->class_loader_data(), new_size, CHECK); @@ -1338,12 +1321,6 @@ (new_method == NULL || orig_method->name() < new_method->name())) { merged_methods->at_put(i, orig_method); original_methods->at_put(orig_idx, NULL); - for (int j = 0; j < NUM_ARRAYS; ++j) { - if (merged_annots[j] != NULL) { - merged_annots[j]->at_put(i, original_annots[j]->at(orig_idx)); - original_annots[j]->at_put(orig_idx, NULL); - } - } if (merged_ordering->length() > 0) { merged_ordering->at_put(i, original_ordering->at(orig_idx)); } @@ -1372,21 +1349,9 @@ // Replace klass methods with new merged lists klass->set_methods(merged_methods); - if (annots != NULL) { - annots->set_methods_annotations(merged_annots[ANNOTATIONS]); - annots->set_methods_parameter_annotations(merged_annots[PARAMETERS]); - annots->set_methods_default_annotations(merged_annots[DEFAULTS]); - } else { - assert(merged_annots[ANNOTATIONS] == NULL, "Must be"); - assert(merged_annots[PARAMETERS] == NULL, "Must be"); - assert(merged_annots[DEFAULTS] == NULL, "Must be"); - } ClassLoaderData* cld = klass->class_loader_data(); MetadataFactory::free_array(cld, original_methods); - for (int i = 0; i < NUM_ARRAYS; ++i) { - MetadataFactory::free_array(cld, original_annots[i]); - } if (original_ordering->length() > 0) { klass->set_method_ordering(merged_ordering); MetadataFactory::free_array(cld, original_ordering); diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/classfile/metadataOnStackMark.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/vm/classfile/metadataOnStackMark.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#include "precompiled.hpp" +#include "classfile/metadataOnStackMark.hpp" +#include "code/codeCache.hpp" +#include "compiler/compileBroker.hpp" +#include "oops/metadata.hpp" +#include "runtime/synchronizer.hpp" +#include "runtime/thread.hpp" +#include "utilities/growableArray.hpp" + + +// Keep track of marked on-stack metadata so it can be cleared. +GrowableArray* _marked_objects = NULL; +NOT_PRODUCT(bool MetadataOnStackMark::_is_active = false;) + +// Walk metadata on the stack and mark it so that redefinition doesn't delete +// it. Class unloading also walks the previous versions and might try to +// delete it, so this class is used by class unloading also. +MetadataOnStackMark::MetadataOnStackMark() { + assert(SafepointSynchronize::is_at_safepoint(), "sanity check"); + NOT_PRODUCT(_is_active = true;) + if (_marked_objects == NULL) { + _marked_objects = new (ResourceObj::C_HEAP, mtClass) GrowableArray(1000, true); + } + Threads::metadata_do(Metadata::mark_on_stack); + CodeCache::alive_nmethods_do(nmethod::mark_on_stack); + CompileBroker::mark_on_stack(); +} + +MetadataOnStackMark::~MetadataOnStackMark() { + assert(SafepointSynchronize::is_at_safepoint(), "sanity check"); + // Unmark everything that was marked. Can't do the same walk because + // redefine classes messes up the code cache so the set of methods + // might not be the same. + for (int i = 0; i< _marked_objects->length(); i++) { + _marked_objects->at(i)->set_on_stack(false); + } + _marked_objects->clear(); // reuse growable array for next time. + NOT_PRODUCT(_is_active = false;) +} + +// Record which objects are marked so we can unmark the same objects. +void MetadataOnStackMark::record(Metadata* m) { + assert(_is_active, "metadata on stack marking is active"); + _marked_objects->push(m); +} diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/classfile/metadataOnStackMark.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/vm/classfile/metadataOnStackMark.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef SHARE_VM_CLASSFILE_METADATAONSTACKMARK_HPP +#define SHARE_VM_CLASSFILE_METADATAONSTACKMARK_HPP + +#include "memory/allocation.hpp" + +class Metadata; + +// Helper class to mark and unmark metadata used on the stack as either handles +// or executing methods, so that it can't be deleted during class redefinition +// and class unloading. +// This is also used for other things that can be deallocated, like class +// metadata during parsing, relocated methods, and methods in backtraces. +class MetadataOnStackMark : public StackObj { + NOT_PRODUCT(static bool _is_active;) + public: + MetadataOnStackMark(); + ~MetadataOnStackMark(); + static void record(Metadata* m); +}; + +#endif // SHARE_VM_CLASSFILE_METADATAONSTACKMARK_HPP diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/classfile/stackMapFrame.hpp --- a/src/share/vm/classfile/stackMapFrame.hpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/classfile/stackMapFrame.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -178,7 +178,7 @@ #ifdef DEBUG // Put bogus type to indicate it's no longer valid. if (_stack_mark != -1) { - for (int i = _stack_mark; i >= _stack_size; --i) { + for (int i = _stack_mark - 1; i >= _stack_size; --i) { _stack[i] = VerificationType::bogus_type(); } } diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/classfile/systemDictionary.cpp --- a/src/share/vm/classfile/systemDictionary.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/classfile/systemDictionary.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -1199,66 +1199,6 @@ return ik; } -#ifdef KERNEL -// Some classes on the bootstrap class path haven't been installed on the -// system yet. Call the DownloadManager method to make them appear in the -// bootstrap class path and try again to load the named class. -// Note that with delegation class loaders all classes in another loader will -// first try to call this so it'd better be fast!! -static instanceKlassHandle download_and_retry_class_load( - Symbol* class_name, - TRAPS) { - - Klass* dlm = SystemDictionary::DownloadManager_klass(); - instanceKlassHandle nk; - - // If download manager class isn't loaded just return. - if (dlm == NULL) return nk; - - { HandleMark hm(THREAD); - ResourceMark rm(THREAD); - Handle s = java_lang_String::create_from_symbol(class_name, CHECK_(nk)); - Handle class_string = java_lang_String::externalize_classname(s, CHECK_(nk)); - - // return value - JavaValue result(T_OBJECT); - - // Call the DownloadManager. We assume that it has a lock because - // multiple classes could be not found and downloaded at the same time. - // class sun.misc.DownloadManager; - // public static String getBootClassPathEntryForClass(String className); - JavaCalls::call_static(&result, - KlassHandle(THREAD, dlm), - vmSymbols::getBootClassPathEntryForClass_name(), - vmSymbols::string_string_signature(), - class_string, - CHECK_(nk)); - - // Get result.string and add to bootclasspath - assert(result.get_type() == T_OBJECT, "just checking"); - oop obj = (oop) result.get_jobject(); - if (obj == NULL) { return nk; } - - Handle h_obj(THREAD, obj); - char* new_class_name = java_lang_String::as_platform_dependent_str(h_obj, - CHECK_(nk)); - - // lock the loader - // we use this lock because JVMTI does. - Handle loader_lock(THREAD, SystemDictionary::system_loader_lock()); - - ObjectLocker ol(loader_lock, THREAD); - // add the file to the bootclasspath - ClassLoader::update_class_path_entry_list(new_class_name, true); - } // end HandleMark - - if (TraceClassLoading) { - ClassLoader::print_bootclasspath(); - } - return ClassLoader::load_classfile(class_name, CHECK_(nk)); -} -#endif // KERNEL - instanceKlassHandle SystemDictionary::load_instance_class(Symbol* class_name, Handle class_loader, TRAPS) { instanceKlassHandle nh = instanceKlassHandle(); // null Handle @@ -1278,15 +1218,6 @@ k = ClassLoader::load_classfile(class_name, CHECK_(nh)); } -#ifdef KERNEL - // If the VM class loader has failed to load the class, call the - // DownloadManager class to make it magically appear on the classpath - // and try again. This is only configured with the Kernel VM. - if (k.is_null()) { - k = download_and_retry_class_load(class_name, CHECK_(nh)); - } -#endif // KERNEL - // find_or_define_instance_class may return a different InstanceKlass if (!k.is_null()) { k = find_or_define_instance_class(class_name, class_loader, k, CHECK_(nh)); @@ -1822,13 +1753,7 @@ Symbol* symbol = vmSymbols::symbol_at((vmSymbols::SID)sid); Klass** klassp = &_well_known_klasses[id]; bool must_load = (init_opt < SystemDictionary::Opt); - bool try_load = true; - if (init_opt == SystemDictionary::Opt_Kernel) { -#ifndef KERNEL - try_load = false; -#endif //KERNEL - } - if ((*klassp) == NULL && try_load) { + if ((*klassp) == NULL) { if (must_load) { (*klassp) = resolve_or_fail(symbol, true, CHECK_0); // load required class } else { @@ -1918,12 +1843,6 @@ //_box_klasses[T_OBJECT] = WK_KLASS(object_klass); //_box_klasses[T_ARRAY] = WK_KLASS(object_klass); -#ifdef KERNEL - if (DownloadManager_klass() == NULL) { - warning("Cannot find sun/jkernel/DownloadManager"); - } -#endif // KERNEL - { // Compute whether we should use loadClass or loadClassInternal when loading classes. Method* method = InstanceKlass::cast(ClassLoader_klass())->find_method(vmSymbols::loadClassInternal_name(), vmSymbols::string_class_signature()); _has_loadClassInternal = (method != NULL); diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/classfile/systemDictionary.hpp --- a/src/share/vm/classfile/systemDictionary.hpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/classfile/systemDictionary.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -168,8 +168,6 @@ /* It's okay if this turns out to be NULL in non-1.4 JDKs. */ \ do_klass(nio_Buffer_klass, java_nio_Buffer, Opt ) \ \ - do_klass(DownloadManager_klass, sun_jkernel_DownloadManager, Opt_Kernel ) \ - \ do_klass(PostVMInitHook_klass, sun_misc_PostVMInitHook, Opt ) \ \ /* Preload boxing klasses */ \ @@ -253,7 +251,6 @@ Opt, // preload tried; NULL if not present Opt_Only_JDK14NewRef, // preload tried; use only with NewReflection Opt_Only_JDK15, // preload tried; use only with JDK1.5+ - Opt_Kernel, // preload tried only #ifdef KERNEL OPTION_LIMIT, CEIL_LG_OPTION_LIMIT = 4 // OPTION_LIMIT <= (1<major_version() < STATIC_METHOD_IN_INTERFACE_MAJOR_VERSION) ? + (1 << JVM_CONSTANT_Methodref) : + ((1 << JVM_CONSTANT_InterfaceMethodref) | (1 << JVM_CONSTANT_Methodref)); + break; default: types = 1 << JVM_CONSTANT_Methodref; } diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/classfile/vmSymbols.hpp --- a/src/share/vm/classfile/vmSymbols.hpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/classfile/vmSymbols.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -108,7 +108,6 @@ template(java_lang_Compiler, "java/lang/Compiler") \ template(sun_misc_Signal, "sun/misc/Signal") \ template(java_lang_AssertionStatusDirectives, "java/lang/AssertionStatusDirectives") \ - template(sun_jkernel_DownloadManager, "sun/jkernel/DownloadManager") \ template(getBootClassPathEntryForClass_name, "getBootClassPathEntryForClass") \ template(sun_misc_PostVMInitHook, "sun/misc/PostVMInitHook") \ template(sun_misc_Launcher_ExtClassLoader, "sun/misc/Launcher$ExtClassLoader") \ diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/compiler/compileBroker.cpp --- a/src/share/vm/compiler/compileBroker.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/compiler/compileBroker.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -1421,7 +1421,7 @@ method->print_short_name(tty); tty->cr(); } - method->set_not_compilable_quietly(); + method->set_not_compilable(CompLevel_all, !quietly, "excluded by CompilerOracle"); } return false; diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp --- a/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -102,7 +102,7 @@ // temporarily disabled). switch (dictionaryChoice) { case FreeBlockDictionary::dictionaryBinaryTree: - _dictionary = new BinaryTreeDictionary(mr); + _dictionary = new AFLBinaryTreeDictionary(mr); break; case FreeBlockDictionary::dictionarySplayTree: case FreeBlockDictionary::dictionarySkipList: @@ -122,7 +122,8 @@ // moved to its new location before the klass is moved. // Set the _refillSize for the linear allocation blocks if (!use_adaptive_freelists) { - FreeChunk* fc = _dictionary->get_chunk(mr.word_size()); + FreeChunk* fc = _dictionary->get_chunk(mr.word_size(), + FreeBlockDictionary::atLeast); // The small linAB initially has all the space and will allocate // a chunk of any size. HeapWord* addr = (HeapWord*) fc; @@ -1647,7 +1648,8 @@ FreeChunk* CompactibleFreeListSpace::getChunkFromDictionary(size_t size) { assert_locked(); - FreeChunk* fc = _dictionary->get_chunk(size); + FreeChunk* fc = _dictionary->get_chunk(size, + FreeBlockDictionary::atLeast); if (fc == NULL) { return NULL; } @@ -1664,7 +1666,8 @@ FreeChunk* CompactibleFreeListSpace::getChunkFromDictionaryExact(size_t size) { assert_locked(); - FreeChunk* fc = _dictionary->get_chunk(size); + FreeChunk* fc = _dictionary->get_chunk(size, + FreeBlockDictionary::atLeast); if (fc == NULL) { return fc; } @@ -1677,7 +1680,8 @@ if (fc->size() < size + MinChunkSize) { // Return the chunk to the dictionary and go get a bigger one. returnChunkToDictionary(fc); - fc = _dictionary->get_chunk(size + MinChunkSize); + fc = _dictionary->get_chunk(size + MinChunkSize, + FreeBlockDictionary::atLeast); if (fc == NULL) { return NULL; } diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp --- a/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -131,7 +131,7 @@ LinearAllocBlock _smallLinearAllocBlock; FreeBlockDictionary::DictionaryChoice _dictionaryChoice; - FreeBlockDictionary* _dictionary; // ptr to dictionary for large size blocks + AFLBinaryTreeDictionary* _dictionary; // ptr to dictionary for large size blocks AdaptiveFreeList _indexedFreeList[IndexSetSize]; // indexed array for small size blocks diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp --- a/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -274,8 +274,8 @@ // end of a collection, we let CMSTriggerRatio of the (purported) free // space be allocated before initiating a new collection cycle. // -void ConcurrentMarkSweepGeneration::init_initiating_occupancy(intx io, intx tr) { - assert(io <= 100 && tr >= 0 && tr <= 100, "Check the arguments"); +void ConcurrentMarkSweepGeneration::init_initiating_occupancy(intx io, uintx tr) { + assert(io <= 100 && tr <= 100, "Check the arguments"); if (io >= 0) { _initiating_occupancy = (double)io / 100.0; } else { diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp --- a/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1093,7 +1093,7 @@ // getter and initializer for _initiating_occupancy field. double initiating_occupancy() const { return _initiating_occupancy; } - void init_initiating_occupancy(intx io, intx tr); + void init_initiating_occupancy(intx io, uintx tr); public: ConcurrentMarkSweepGeneration(ReservedSpace rs, size_t initial_byte_size, diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/gc_implementation/concurrentMarkSweep/vmStructs_cms.hpp --- a/src/share/vm/gc_implementation/concurrentMarkSweep/vmStructs_cms.hpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/gc_implementation/concurrentMarkSweep/vmStructs_cms.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,8 +25,6 @@ #ifndef SHARE_VM_GC_IMPLEMENTATION_CONCURRENTMARKSWEEP_VMSTRUCTS_CMS_HPP #define SHARE_VM_GC_IMPLEMENTATION_CONCURRENTMARKSWEEP_VMSTRUCTS_CMS_HPP -typedef BinaryTreeDictionary AFLBinaryTreeDictionary; - #define VM_STRUCTS_CMS(nonstatic_field, \ volatile_nonstatic_field, \ static_field) \ @@ -34,14 +32,15 @@ nonstatic_field(CompactibleFreeListSpace, _bt, BlockOffsetArrayNonContigSpace) \ \ nonstatic_field(CMSBitMap, _bmWordSize, size_t) \ - nonstatic_field(CMSBitMap, _shifter, const int) \ - nonstatic_field(CMSBitMap, _bm, BitMap) \ - nonstatic_field(CMSBitMap, _virtual_space, VirtualSpace) \ + nonstatic_field(CMSBitMap, _shifter, const int) \ + nonstatic_field(CMSBitMap, _bm, BitMap) \ + nonstatic_field(CMSBitMap, _virtual_space, VirtualSpace) \ nonstatic_field(CMSCollector, _markBitMap, CMSBitMap) \ nonstatic_field(ConcurrentMarkSweepGeneration, _cmsSpace, CompactibleFreeListSpace*) \ static_field(ConcurrentMarkSweepThread, _collector, CMSCollector*) \ nonstatic_field(LinearAllocBlock, _word_size, size_t) \ nonstatic_field(AFLBinaryTreeDictionary, _total_size, size_t) \ + nonstatic_field(CompactibleFreeListSpace, _dictionary, AFLBinaryTreeDictionary*) \ nonstatic_field(CompactibleFreeListSpace, _indexedFreeList[0], FreeList) \ nonstatic_field(CompactibleFreeListSpace, _smallLinearAllocBlock, LinearAllocBlock) @@ -62,10 +61,9 @@ declare_toplevel_type(SurrogateLockerThread*) \ declare_toplevel_type(CompactibleFreeListSpace*) \ declare_toplevel_type(CMSCollector*) \ - declare_toplevel_type(AFLBinaryTreeDictionary*) \ + declare_toplevel_type(AFLBinaryTreeDictionary) \ declare_toplevel_type(LinearAllocBlock) \ - declare_toplevel_type(FreeBlockDictionary) \ - declare_type(AFLBinaryTreeDictionary, FreeBlockDictionary) + declare_toplevel_type(FreeBlockDictionary) #define VM_INT_CONSTANTS_CMS(declare_constant) \ declare_constant(Generation::ConcurrentMarkSweep) \ diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/gc_implementation/g1/concurrentMark.cpp --- a/src/share/vm/gc_implementation/g1/concurrentMark.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/gc_implementation/g1/concurrentMark.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -571,19 +571,14 @@ _sleep_factor = 0.0; _marking_task_overhead = 1.0; } else { - if (ConcGCThreads > 0) { - // notice that ConcGCThreads overwrites G1MarkingOverheadPercent + if (!FLAG_IS_DEFAULT(ConcGCThreads) && ConcGCThreads > 0) { + // Note: ConcGCThreads has precedence over G1MarkingOverheadPercent // if both are set - - _parallel_marking_threads = (uint) ConcGCThreads; - _max_parallel_marking_threads = _parallel_marking_threads; _sleep_factor = 0.0; _marking_task_overhead = 1.0; } else if (G1MarkingOverheadPercent > 0) { - // we will calculate the number of parallel marking threads - // based on a target overhead with respect to the soft real-time - // goal - + // We will calculate the number of parallel marking threads based + // on a target overhead with respect to the soft real-time goal double marking_overhead = (double) G1MarkingOverheadPercent / 100.0; double overall_cm_overhead = (double) MaxGCPauseMillis * marking_overhead / @@ -596,17 +591,22 @@ double sleep_factor = (1.0 - marking_task_overhead) / marking_task_overhead; - _parallel_marking_threads = (uint) marking_thread_num; - _max_parallel_marking_threads = _parallel_marking_threads; + FLAG_SET_ERGO(uintx, ConcGCThreads, (uint) marking_thread_num); _sleep_factor = sleep_factor; _marking_task_overhead = marking_task_overhead; } else { - _parallel_marking_threads = scale_parallel_threads((uint)ParallelGCThreads); - _max_parallel_marking_threads = _parallel_marking_threads; + // Calculate the number of parallel marking threads by scaling + // the number of parallel GC threads. + uint marking_thread_num = scale_parallel_threads((uint) ParallelGCThreads); + FLAG_SET_ERGO(uintx, ConcGCThreads, marking_thread_num); _sleep_factor = 0.0; _marking_task_overhead = 1.0; } + assert(ConcGCThreads > 0, "Should have been set"); + _parallel_marking_threads = (uint) ConcGCThreads; + _max_parallel_marking_threads = _parallel_marking_threads; + if (parallel_marking_threads() > 1) { _cleanup_task_overhead = 1.0; } else { @@ -1190,7 +1190,7 @@ uint active_workers = MAX2(1U, parallel_marking_threads()); CMRootRegionScanTask task(this); - if (parallel_marking_threads() > 0) { + if (use_parallel_marking_threads()) { _parallel_workers->set_active_workers((int) active_workers); _parallel_workers->run_task(&task); } else { @@ -1226,7 +1226,7 @@ set_phase(active_workers, true /* concurrent */); CMConcurrentMarkingTask markingTask(this, cmThread()); - if (parallel_marking_threads() > 0) { + if (use_parallel_marking_threads()) { _parallel_workers->set_active_workers((int)active_workers); // Don't set _n_par_threads because it affects MT in proceess_strong_roots() // and the decisions on that MT processing is made elsewhere. @@ -2167,7 +2167,8 @@ assert(tmp_free_list.is_empty(), "post-condition"); } -// Support closures for reference procssing in G1 +// Supporting Object and Oop closures for reference discovery +// and processing in during marking bool G1CMIsAliveClosure::do_object_b(oop obj) { HeapWord* addr = (HeapWord*)obj; @@ -2175,73 +2176,26 @@ (!_g1->is_in_g1_reserved(addr) || !_g1->is_obj_ill(obj)); } -class G1CMKeepAliveClosure: public ExtendedOopClosure { - G1CollectedHeap* _g1; - ConcurrentMark* _cm; - public: - G1CMKeepAliveClosure(G1CollectedHeap* g1, ConcurrentMark* cm) : - _g1(g1), _cm(cm) { - assert(Thread::current()->is_VM_thread(), "otherwise fix worker id"); - } - - virtual void do_oop(narrowOop* p) { do_oop_work(p); } - virtual void do_oop( oop* p) { do_oop_work(p); } - - template void do_oop_work(T* p) { - oop obj = oopDesc::load_decode_heap_oop(p); - HeapWord* addr = (HeapWord*)obj; - - if (_cm->verbose_high()) { - gclog_or_tty->print_cr("\t[0] we're looking at location " - "*"PTR_FORMAT" = "PTR_FORMAT, - p, (void*) obj); - } - - if (_g1->is_in_g1_reserved(addr) && _g1->is_obj_ill(obj)) { - _cm->mark_and_count(obj); - _cm->mark_stack_push(obj); - } - } -}; - -class G1CMDrainMarkingStackClosure: public VoidClosure { - ConcurrentMark* _cm; - CMMarkStack* _markStack; - G1CMKeepAliveClosure* _oopClosure; - public: - G1CMDrainMarkingStackClosure(ConcurrentMark* cm, CMMarkStack* markStack, - G1CMKeepAliveClosure* oopClosure) : - _cm(cm), - _markStack(markStack), - _oopClosure(oopClosure) { } - - void do_void() { - _markStack->drain(_oopClosure, _cm->nextMarkBitMap(), false); - } -}; - -// 'Keep Alive' closure used by parallel reference processing. -// An instance of this closure is used in the parallel reference processing -// code rather than an instance of G1CMKeepAliveClosure. We could have used -// the G1CMKeepAliveClosure as it is MT-safe. Also reference objects are -// placed on to discovered ref lists once so we can mark and push with no -// need to check whether the object has already been marked. Using the -// G1CMKeepAliveClosure would mean, however, having all the worker threads -// operating on the global mark stack. This means that an individual -// worker would be doing lock-free pushes while it processes its own -// discovered ref list followed by drain call. If the discovered ref lists -// are unbalanced then this could cause interference with the other -// workers. Using a CMTask (and its embedded local data structures) -// avoids that potential interference. -class G1CMParKeepAliveAndDrainClosure: public OopClosure { +// 'Keep Alive' oop closure used by both serial parallel reference processing. +// Uses the CMTask associated with a worker thread (for serial reference +// processing the CMTask for worker 0 is used) to preserve (mark) and +// trace referent objects. +// +// Using the CMTask and embedded local queues avoids having the worker +// threads operating on the global mark stack. This reduces the risk +// of overflowing the stack - which we would rather avoid at this late +// state. Also using the tasks' local queues removes the potential +// of the workers interfering with each other that could occur if +// operating on the global stack. + +class G1CMKeepAliveAndDrainClosure: public OopClosure { ConcurrentMark* _cm; CMTask* _task; int _ref_counter_limit; int _ref_counter; public: - G1CMParKeepAliveAndDrainClosure(ConcurrentMark* cm, CMTask* task) : - _cm(cm), _task(task), - _ref_counter_limit(G1RefProcDrainInterval) { + G1CMKeepAliveAndDrainClosure(ConcurrentMark* cm, CMTask* task) : + _cm(cm), _task(task), _ref_counter_limit(G1RefProcDrainInterval) { assert(_ref_counter_limit > 0, "sanity"); _ref_counter = _ref_counter_limit; } @@ -2262,18 +2216,22 @@ _ref_counter--; if (_ref_counter == 0) { - // We have dealt with _ref_counter_limit references, pushing them and objects - // reachable from them on to the local stack (and possibly the global stack). - // Call do_marking_step() to process these entries. We call the routine in a - // loop, which we'll exit if there's nothing more to do (i.e. we're done - // with the entries that we've pushed as a result of the deal_with_reference - // calls above) or we overflow. - // Note: CMTask::do_marking_step() can set the CMTask::has_aborted() flag - // while there may still be some work to do. (See the comment at the - // beginning of CMTask::do_marking_step() for those conditions - one of which - // is reaching the specified time target.) It is only when - // CMTask::do_marking_step() returns without setting the has_aborted() flag - // that the marking has completed. + // We have dealt with _ref_counter_limit references, pushing them + // and objects reachable from them on to the local stack (and + // possibly the global stack). Call CMTask::do_marking_step() to + // process these entries. + // + // We call CMTask::do_marking_step() in a loop, which we'll exit if + // there's nothing more to do (i.e. we're done with the entries that + // were pushed as a result of the CMTask::deal_with_reference() calls + // above) or we overflow. + // + // Note: CMTask::do_marking_step() can set the CMTask::has_aborted() + // flag while there may still be some work to do. (See the comment at + // the beginning of CMTask::do_marking_step() for those conditions - + // one of which is reaching the specified time target.) It is only + // when CMTask::do_marking_step() returns without setting the + // has_aborted() flag that the marking step has completed. do { double mark_step_duration_ms = G1ConcMarkStepDurationMillis; _task->do_marking_step(mark_step_duration_ms, @@ -2290,36 +2248,59 @@ } }; -class G1CMParDrainMarkingStackClosure: public VoidClosure { +// 'Drain' oop closure used by both serial and parallel reference processing. +// Uses the CMTask associated with a given worker thread (for serial +// reference processing the CMtask for worker 0 is used). Calls the +// do_marking_step routine, with an unbelievably large timeout value, +// to drain the marking data structures of the remaining entries +// added by the 'keep alive' oop closure above. + +class G1CMDrainMarkingStackClosure: public VoidClosure { ConcurrentMark* _cm; - CMTask* _task; + CMTask* _task; + bool _do_stealing; + bool _do_termination; public: - G1CMParDrainMarkingStackClosure(ConcurrentMark* cm, CMTask* task) : - _cm(cm), _task(task) { } + G1CMDrainMarkingStackClosure(ConcurrentMark* cm, CMTask* task, bool is_par) : + _cm(cm), _task(task) { + assert(is_par || _task->worker_id() == 0, + "Only task for worker 0 should be used if ref processing is single threaded"); + // We only allow stealing and only enter the termination protocol + // in CMTask::do_marking_step() if this closure is being instantiated + // for parallel reference processing. + _do_stealing = _do_termination = is_par; + } void do_void() { do { if (_cm->verbose_high()) { - gclog_or_tty->print_cr("\t[%u] Drain: Calling do marking_step", - _task->worker_id()); + gclog_or_tty->print_cr("\t[%u] Drain: Calling do_marking_step - " + "stealing: %s, termination: %s", + _task->worker_id(), + BOOL_TO_STR(_do_stealing), + BOOL_TO_STR(_do_termination)); } - // We call CMTask::do_marking_step() to completely drain the local and - // global marking stacks. The routine is called in a loop, which we'll - // exit if there's nothing more to do (i.e. we'completely drained the - // entries that were pushed as a result of applying the - // G1CMParKeepAliveAndDrainClosure to the entries on the discovered ref - // lists above) or we overflow the global marking stack. - // Note: CMTask::do_marking_step() can set the CMTask::has_aborted() flag - // while there may still be some work to do. (See the comment at the - // beginning of CMTask::do_marking_step() for those conditions - one of which - // is reaching the specified time target.) It is only when - // CMTask::do_marking_step() returns without setting the has_aborted() flag - // that the marking has completed. + // We call CMTask::do_marking_step() to completely drain the local + // and global marking stacks of entries pushed by the 'keep alive' + // oop closure (an instance of G1CMKeepAliveAndDrainClosure above). + // + // CMTask::do_marking_step() is called in a loop, which we'll exit + // if there's nothing more to do (i.e. we'completely drained the + // entries that were pushed as a a result of applying the 'keep alive' + // closure to the entries on the discovered ref lists) or we overflow + // the global marking stack. + // + // Note: CMTask::do_marking_step() can set the CMTask::has_aborted() + // flag while there may still be some work to do. (See the comment at + // the beginning of CMTask::do_marking_step() for those conditions - + // one of which is reaching the specified time target.) It is only + // when CMTask::do_marking_step() returns without setting the + // has_aborted() flag that the marking step has completed. _task->do_marking_step(1000000000.0 /* something very large */, - true /* do_stealing */, - true /* do_termination */); + _do_stealing, + _do_termination); } while (_task->has_aborted() && !_cm->has_overflown()); } }; @@ -2352,19 +2333,23 @@ ProcessTask& _proc_task; G1CollectedHeap* _g1h; ConcurrentMark* _cm; + bool _processing_is_mt; public: G1CMRefProcTaskProxy(ProcessTask& proc_task, G1CollectedHeap* g1h, ConcurrentMark* cm) : AbstractGangTask("Process reference objects in parallel"), - _proc_task(proc_task), _g1h(g1h), _cm(cm) { } + _proc_task(proc_task), _g1h(g1h), _cm(cm) { + ReferenceProcessor* rp = _g1h->ref_processor_cm(); + _processing_is_mt = rp->processing_is_mt(); + } virtual void work(uint worker_id) { CMTask* marking_task = _cm->task(worker_id); G1CMIsAliveClosure g1_is_alive(_g1h); - G1CMParKeepAliveAndDrainClosure g1_par_keep_alive(_cm, marking_task); - G1CMParDrainMarkingStackClosure g1_par_drain(_cm, marking_task); + G1CMKeepAliveAndDrainClosure g1_par_keep_alive(_cm, marking_task); + G1CMDrainMarkingStackClosure g1_par_drain(_cm, marking_task, _processing_is_mt); _proc_task.work(worker_id, g1_is_alive, g1_par_keep_alive, g1_par_drain); } @@ -2372,6 +2357,7 @@ void G1CMRefProcTaskExecutor::execute(ProcessTask& proc_task) { assert(_workers != NULL, "Need parallel worker threads."); + assert(_g1h->ref_processor_cm()->processing_is_mt(), "processing is not MT"); G1CMRefProcTaskProxy proc_task_proxy(proc_task, _g1h, _cm); @@ -2399,6 +2385,7 @@ void G1CMRefProcTaskExecutor::execute(EnqueueTask& enq_task) { assert(_workers != NULL, "Need parallel worker threads."); + assert(_g1h->ref_processor_cm()->processing_is_mt(), "processing is not MT"); G1CMRefEnqueueTaskProxy enq_task_proxy(enq_task); @@ -2429,59 +2416,58 @@ // See the comment in G1CollectedHeap::ref_processing_init() // about how reference processing currently works in G1. - // Process weak references. + // Set the soft reference policy rp->setup_policy(clear_all_soft_refs); assert(_markStack.isEmpty(), "mark stack should be empty"); - G1CMKeepAliveClosure g1_keep_alive(g1h, this); - G1CMDrainMarkingStackClosure - g1_drain_mark_stack(this, &_markStack, &g1_keep_alive); - - // We use the work gang from the G1CollectedHeap and we utilize all - // the worker threads. - uint active_workers = g1h->workers() ? g1h->workers()->active_workers() : 1U; + // Non-MT instances 'Keep Alive' and 'Complete GC' oop closures. + G1CMKeepAliveAndDrainClosure g1_keep_alive(this, task(0)); + G1CMDrainMarkingStackClosure g1_drain_mark_stack(this, task(0), false); + + // We need at least one active thread. If reference processing is + // not multi-threaded we use the current (ConcurrentMarkThread) thread, + // otherwise we use the work gang from the G1CollectedHeap and we + // utilize all the worker threads we can. + uint active_workers = (rp->processing_is_mt() && g1h->workers() != NULL + ? g1h->workers()->active_workers() + : 1U); + active_workers = MAX2(MIN2(active_workers, _max_worker_id), 1U); G1CMRefProcTaskExecutor par_task_executor(g1h, this, g1h->workers(), active_workers); - if (rp->processing_is_mt()) { - // Set the degree of MT here. If the discovery is done MT, there - // may have been a different number of threads doing the discovery - // and a different number of discovered lists may have Ref objects. - // That is OK as long as the Reference lists are balanced (see - // balance_all_queues() and balance_queues()). - rp->set_active_mt_degree(active_workers); - - rp->process_discovered_references(&g1_is_alive, + AbstractRefProcTaskExecutor* executor = (rp->processing_is_mt() + ? &par_task_executor + : NULL); + + // Set the degree of MT processing here. If the discovery was done MT, + // the number of threads involved during discovery could differ from + // the number of active workers. This is OK as long as the discovered + // Reference lists are balanced (see balance_all_queues() and balance_queues()). + rp->set_active_mt_degree(active_workers); + + // Process the weak references. + rp->process_discovered_references(&g1_is_alive, &g1_keep_alive, &g1_drain_mark_stack, - &par_task_executor); - - // The work routines of the parallel keep_alive and drain_marking_stack - // will set the has_overflown flag if we overflow the global marking - // stack. - } else { - rp->process_discovered_references(&g1_is_alive, - &g1_keep_alive, - &g1_drain_mark_stack, - NULL); - } + executor); + + // The do_oop work routines of the keep_alive and drain_marking_stack + // oop closures will set the has_overflown flag if we overflow the + // global marking stack. assert(_markStack.overflow() || _markStack.isEmpty(), "mark stack should be empty (unless it overflowed)"); if (_markStack.overflow()) { - // Should have been done already when we tried to push an + // This should have been done already when we tried to push an // entry on to the global mark stack. But let's do it again. set_has_overflown(); } - if (rp->processing_is_mt()) { - assert(rp->num_q() == active_workers, "why not"); - rp->enqueue_discovered_references(&par_task_executor); - } else { - rp->enqueue_discovered_references(); - } + assert(rp->num_q() == active_workers, "why not"); + + rp->enqueue_discovered_references(executor); rp->verify_no_references_recorded(); assert(!rp->discovery_enabled(), "Post condition"); @@ -3242,7 +3228,9 @@ } void ConcurrentMark::print_worker_threads_on(outputStream* st) const { - _parallel_workers->print_worker_threads_on(st); + if (use_parallel_marking_threads()) { + _parallel_workers->print_worker_threads_on(st); + } } // We take a break if someone is trying to stop the world. @@ -4074,15 +4062,36 @@ if (_cm->verbose_low()) { gclog_or_tty->print_cr("[%u] we're scanning part " "["PTR_FORMAT", "PTR_FORMAT") " - "of region "PTR_FORMAT, - _worker_id, _finger, _region_limit, _curr_region); + "of region "HR_FORMAT, + _worker_id, _finger, _region_limit, + HR_FORMAT_PARAMS(_curr_region)); } - // Let's iterate over the bitmap of the part of the - // region that is left. - if (mr.is_empty() || _nextMarkBitMap->iterate(&bitmap_closure, mr)) { - // We successfully completed iterating over the region. Now, - // let's give up the region. + assert(!_curr_region->isHumongous() || mr.start() == _curr_region->bottom(), + "humongous regions should go around loop once only"); + + // Some special cases: + // If the memory region is empty, we can just give up the region. + // If the current region is humongous then we only need to check + // the bitmap for the bit associated with the start of the object, + // scan the object if it's live, and give up the region. + // Otherwise, let's iterate over the bitmap of the part of the region + // that is left. + // If the iteration is successful, give up the region. + if (mr.is_empty()) { + giveup_current_region(); + regular_clock_call(); + } else if (_curr_region->isHumongous() && mr.start() == _curr_region->bottom()) { + if (_nextMarkBitMap->isMarked(mr.start())) { + // The object is marked - apply the closure + BitMap::idx_t offset = _nextMarkBitMap->heapWordToOffset(mr.start()); + bitmap_closure.do_bit(offset); + } + // Even if this task aborted while scanning the humongous object + // we can (and should) give up the current region. + giveup_current_region(); + regular_clock_call(); + } else if (_nextMarkBitMap->iterate(&bitmap_closure, mr)) { giveup_current_region(); regular_clock_call(); } else { diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/gc_implementation/g1/concurrentMark.hpp --- a/src/share/vm/gc_implementation/g1/concurrentMark.hpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/gc_implementation/g1/concurrentMark.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -371,8 +371,8 @@ friend class CalcLiveObjectsClosure; friend class G1CMRefProcTaskProxy; friend class G1CMRefProcTaskExecutor; - friend class G1CMParKeepAliveAndDrainClosure; - friend class G1CMParDrainMarkingStackClosure; + friend class G1CMKeepAliveAndDrainClosure; + friend class G1CMDrainMarkingStackClosure; protected: ConcurrentMarkThread* _cmThread; // the thread doing the work @@ -499,17 +499,26 @@ } // accessor methods - uint parallel_marking_threads() { return _parallel_marking_threads; } - uint max_parallel_marking_threads() { return _max_parallel_marking_threads;} - double sleep_factor() { return _sleep_factor; } - double marking_task_overhead() { return _marking_task_overhead;} - double cleanup_sleep_factor() { return _cleanup_sleep_factor; } - double cleanup_task_overhead() { return _cleanup_task_overhead;} + uint parallel_marking_threads() const { return _parallel_marking_threads; } + uint max_parallel_marking_threads() const { return _max_parallel_marking_threads;} + double sleep_factor() { return _sleep_factor; } + double marking_task_overhead() { return _marking_task_overhead;} + double cleanup_sleep_factor() { return _cleanup_sleep_factor; } + double cleanup_task_overhead() { return _cleanup_task_overhead;} - HeapWord* finger() { return _finger; } - bool concurrent() { return _concurrent; } - uint active_tasks() { return _active_tasks; } - ParallelTaskTerminator* terminator() { return &_terminator; } + bool use_parallel_marking_threads() const { + assert(parallel_marking_threads() <= + max_parallel_marking_threads(), "sanity"); + assert((_parallel_workers == NULL && parallel_marking_threads() == 0) || + parallel_marking_threads() > 0, + "parallel workers not set up correctly"); + return _parallel_workers != NULL; + } + + HeapWord* finger() { return _finger; } + bool concurrent() { return _concurrent; } + uint active_tasks() { return _active_tasks; } + ParallelTaskTerminator* terminator() { return &_terminator; } // It claims the next available region to be scanned by a marking // task/thread. It might return NULL if the next region is empty or diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/gc_implementation/g1/concurrentMarkThread.cpp --- a/src/share/vm/gc_implementation/g1/concurrentMarkThread.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/gc_implementation/g1/concurrentMarkThread.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -117,7 +117,7 @@ if (G1Log::fine()) { gclog_or_tty->date_stamp(PrintGCDateStamps); gclog_or_tty->stamp(PrintGCTimeStamps); - gclog_or_tty->print_cr("[GC concurrent-root-region-scan-end, %1.7lf]", + gclog_or_tty->print_cr("[GC concurrent-root-region-scan-end, %1.7lf secs]", scan_end - scan_start); } } @@ -150,7 +150,7 @@ if (G1Log::fine()) { gclog_or_tty->date_stamp(PrintGCDateStamps); gclog_or_tty->stamp(PrintGCTimeStamps); - gclog_or_tty->print_cr("[GC concurrent-mark-end, %1.7lf sec]", + gclog_or_tty->print_cr("[GC concurrent-mark-end, %1.7lf secs]", mark_end_sec - mark_start_sec); } @@ -234,7 +234,7 @@ if (G1Log::fine()) { gclog_or_tty->date_stamp(PrintGCDateStamps); gclog_or_tty->stamp(PrintGCTimeStamps); - gclog_or_tty->print_cr("[GC concurrent-cleanup-end, %1.7lf]", + gclog_or_tty->print_cr("[GC concurrent-cleanup-end, %1.7lf secs]", cleanup_end_sec - cleanup_start_sec); } } diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp --- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -1893,7 +1893,6 @@ _ref_processor_stw(NULL), _process_strong_tasks(new SubTasksDone(G1H_PS_NumElements)), _bot_shared(NULL), - _objs_with_preserved_marks(NULL), _preserved_marks_of_objs(NULL), _evac_failure_scan_stack(NULL) , _mark_in_progress(false), _cg1r(NULL), _summary_bytes_used(0), @@ -4215,22 +4214,15 @@ assert(check_cset_heap_region_claim_values(HeapRegion::InitialClaimValue), "sanity"); // Now restore saved marks, if any. - if (_objs_with_preserved_marks != NULL) { - assert(_preserved_marks_of_objs != NULL, "Both or none."); - guarantee(_objs_with_preserved_marks->length() == - _preserved_marks_of_objs->length(), "Both or none."); - for (int i = 0; i < _objs_with_preserved_marks->length(); i++) { - oop obj = _objs_with_preserved_marks->at(i); - markOop m = _preserved_marks_of_objs->at(i); - obj->set_mark(m); - } - - // Delete the preserved marks growable arrays (allocated on the C heap). - delete _objs_with_preserved_marks; - delete _preserved_marks_of_objs; - _objs_with_preserved_marks = NULL; - _preserved_marks_of_objs = NULL; - } + assert(_objs_with_preserved_marks.size() == + _preserved_marks_of_objs.size(), "Both or none."); + while (!_objs_with_preserved_marks.is_empty()) { + oop obj = _objs_with_preserved_marks.pop(); + markOop m = _preserved_marks_of_objs.pop(); + obj->set_mark(m); + } + _objs_with_preserved_marks.clear(true); + _preserved_marks_of_objs.clear(true); } void G1CollectedHeap::push_on_evac_failure_scan_stack(oop obj) { @@ -4313,15 +4305,8 @@ // We want to call the "for_promotion_failure" version only in the // case of a promotion failure. if (m->must_be_preserved_for_promotion_failure(obj)) { - if (_objs_with_preserved_marks == NULL) { - assert(_preserved_marks_of_objs == NULL, "Both or none."); - _objs_with_preserved_marks = - new (ResourceObj::C_HEAP, mtGC) GrowableArray(40, true); - _preserved_marks_of_objs = - new (ResourceObj::C_HEAP, mtGC) GrowableArray(40, true); - } - _objs_with_preserved_marks->push(obj); - _preserved_marks_of_objs->push(m); + _objs_with_preserved_marks.push(obj); + _preserved_marks_of_objs.push(m); } } diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp --- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -37,6 +37,7 @@ #include "memory/barrierSet.hpp" #include "memory/memRegion.hpp" #include "memory/sharedHeap.hpp" +#include "utilities/stack.hpp" // A "G1CollectedHeap" is an implementation of a java heap for HotSpot. // It uses the "Garbage First" heap organization and algorithm, which @@ -877,10 +878,9 @@ // forwarding pointers to themselves. Reset them. void remove_self_forwarding_pointers(); - // When one is non-null, so is the other. Together, they each pair is - // an object with a preserved mark, and its mark value. - GrowableArray* _objs_with_preserved_marks; - GrowableArray* _preserved_marks_of_objs; + // Together, these store an object with a preserved mark, and its mark value. + Stack _objs_with_preserved_marks; + Stack _preserved_marks_of_objs; // Preserve the mark of "obj", if necessary, in preparation for its mark // word being overwritten with a self-forwarding-pointer. diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp --- a/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -267,7 +267,15 @@ double max_gc_time = (double) MaxGCPauseMillis / 1000.0; double time_slice = (double) GCPauseIntervalMillis / 1000.0; _mmu_tracker = new G1MMUTrackerQueue(time_slice, max_gc_time); - _sigma = (double) G1ConfidencePercent / 100.0; + + uintx confidence_perc = G1ConfidencePercent; + // Put an artificial ceiling on this so that it's not set to a silly value. + if (confidence_perc > 100) { + confidence_perc = 100; + warning("G1ConfidencePercent is set to a value that is too large, " + "it's been updated to %u", confidence_perc); + } + _sigma = (double) confidence_perc / 100.0; // start conservatively (around 50ms is about right) _concurrent_mark_remark_times_ms->add(0.05); diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/gc_implementation/g1/g1SATBCardTableModRefBS.hpp --- a/src/share/vm/gc_implementation/g1/g1SATBCardTableModRefBS.hpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/gc_implementation/g1/g1SATBCardTableModRefBS.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -28,8 +28,9 @@ #include "memory/cardTableModRefBS.hpp" #include "memory/memRegion.hpp" #include "oops/oop.inline.hpp" +#include "utilities/macros.hpp" -#ifndef SERIALGC +#if INCLUDE_ALL_GCS class DirtyCardQueueSet; @@ -120,6 +121,6 @@ }; -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS #endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1SATBCARDTABLEMODREFBS_HPP diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/gc_implementation/g1/g1_globals.hpp --- a/src/share/vm/gc_implementation/g1/g1_globals.hpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/gc_implementation/g1/g1_globals.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -32,7 +32,7 @@ #define G1_FLAGS(develop, develop_pd, product, product_pd, diagnostic, experimental, notproduct, manageable, product_rw) \ \ - product(intx, G1ConfidencePercent, 50, \ + product(uintx, G1ConfidencePercent, 50, \ "Confidence level for MMU/pause predictions") \ \ develop(intx, G1MarkingOverheadPercent, 0, \ @@ -101,9 +101,6 @@ "to-space, we will allow regions whose survival rate is up to " \ "S + (1 - S)*X, where X is this parameter (as a fraction.)") \ \ - develop(intx, G1InitYoungSurvRatio, 50, \ - "Expected Survival Rate for newly allocated bytes") \ - \ develop(bool, G1SATBPrintStubs, false, \ "If true, print generated stubs for the SATB barrier") \ \ diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/gc_implementation/g1/heapRegion.hpp --- a/src/share/vm/gc_implementation/g1/heapRegion.hpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/gc_implementation/g1/heapRegion.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -32,8 +32,9 @@ #include "gc_implementation/shared/spaceDecorator.hpp" #include "memory/space.inline.hpp" #include "memory/watermark.hpp" +#include "utilities/macros.hpp" -#ifndef SERIALGC +#if INCLUDE_ALL_GCS // A HeapRegion is the smallest piece of a G1CollectedHeap that // can be collected independently. @@ -837,6 +838,6 @@ bool complete() { return _complete; } }; -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS #endif // SHARE_VM_GC_IMPLEMENTATION_G1_HEAPREGION_HPP diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/gc_implementation/shared/allocationStats.cpp --- a/src/share/vm/gc_implementation/shared/allocationStats.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/gc_implementation/shared/allocationStats.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -23,10 +23,11 @@ */ #include "precompiled.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/shared/allocationStats.hpp" #include "utilities/ostream.hpp" -#endif +#endif // INCLUDE_ALL_GCS // Technically this should be derived from machine speed, and // ideally it would be dynamically adjusted. diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/gc_implementation/shared/allocationStats.hpp --- a/src/share/vm/gc_implementation/shared/allocationStats.hpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/gc_implementation/shared/allocationStats.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -25,11 +25,12 @@ #ifndef SHARE_VM_GC_IMPLEMENTATION_SHARED_ALLOCATIONSTATS_HPP #define SHARE_VM_GC_IMPLEMENTATION_SHARED_ALLOCATIONSTATS_HPP -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/shared/gcUtil.hpp" #include "memory/allocation.hpp" #include "utilities/globalDefinitions.hpp" -#endif +#endif // INCLUDE_ALL_GCS class AllocationStats VALUE_OBJ_CLASS_SPEC { // A duration threshold (in ms) used to filter diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/gc_implementation/shared/concurrentGCThread.hpp --- a/src/share/vm/gc_implementation/shared/concurrentGCThread.hpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/gc_implementation/shared/concurrentGCThread.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -25,9 +25,10 @@ #ifndef SHARE_VM_GC_IMPLEMENTATION_SHARED_CONCURRENTGCTHREAD_HPP #define SHARE_VM_GC_IMPLEMENTATION_SHARED_CONCURRENTGCTHREAD_HPP -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "runtime/thread.hpp" -#endif +#endif // INCLUDE_ALL_GCS class VoidClosure; diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/gc_implementation/shared/gSpaceCounters.cpp --- a/src/share/vm/gc_implementation/shared/gSpaceCounters.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/gc_implementation/shared/gSpaceCounters.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -23,11 +23,12 @@ */ #include "precompiled.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/shared/gSpaceCounters.hpp" #include "memory/generation.hpp" #include "memory/resourceArea.hpp" -#endif +#endif // INCLUDE_ALL_GCS GSpaceCounters::GSpaceCounters(const char* name, int ordinal, size_t max_size, Generation* g, GenerationCounters* gc, diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/gc_implementation/shared/gSpaceCounters.hpp --- a/src/share/vm/gc_implementation/shared/gSpaceCounters.hpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/gc_implementation/shared/gSpaceCounters.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -25,11 +25,12 @@ #ifndef SHARE_VM_GC_IMPLEMENTATION_SHARED_GSPACECOUNTERS_HPP #define SHARE_VM_GC_IMPLEMENTATION_SHARED_GSPACECOUNTERS_HPP -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/shared/generationCounters.hpp" #include "memory/generation.hpp" #include "runtime/perfData.hpp" -#endif +#endif // INCLUDE_ALL_GCS // A GSpaceCounter is a holder class for performance counters // that track a space; diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/gc_implementation/shared/gcAdaptivePolicyCounters.hpp --- a/src/share/vm/gc_implementation/shared/gcAdaptivePolicyCounters.hpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/gc_implementation/shared/gcAdaptivePolicyCounters.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -25,10 +25,11 @@ #ifndef SHARE_VM_GC_IMPLEMENTATION_SHARED_GCADAPTIVEPOLICYCOUNTERS_HPP #define SHARE_VM_GC_IMPLEMENTATION_SHARED_GCADAPTIVEPOLICYCOUNTERS_HPP -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/shared/adaptiveSizePolicy.hpp" #include "gc_implementation/shared/gcPolicyCounters.hpp" -#endif +#endif // INCLUDE_ALL_GCS // This class keeps statistical information and computes the // size of the heap. diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/gc_implementation/shared/hSpaceCounters.hpp --- a/src/share/vm/gc_implementation/shared/hSpaceCounters.hpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/gc_implementation/shared/hSpaceCounters.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -25,11 +25,12 @@ #ifndef SHARE_VM_GC_IMPLEMENTATION_SHARED_HSPACECOUNTERS_HPP #define SHARE_VM_GC_IMPLEMENTATION_SHARED_HSPACECOUNTERS_HPP -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/shared/generationCounters.hpp" #include "memory/generation.hpp" #include "runtime/perfData.hpp" -#endif +#endif // INCLUDE_ALL_GCS // A HSpaceCounter is a holder class for performance counters // that track a collections (logical spaces) in a heap; diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/gc_implementation/shared/immutableSpace.cpp --- a/src/share/vm/gc_implementation/shared/immutableSpace.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/gc_implementation/shared/immutableSpace.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -23,11 +23,12 @@ */ #include "precompiled.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/shared/immutableSpace.hpp" #include "memory/universe.hpp" #include "oops/oop.inline.hpp" -#endif +#endif // INCLUDE_ALL_GCS void ImmutableSpace::initialize(MemRegion mr) { HeapWord* bottom = mr.start(); diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/gc_implementation/shared/isGCActiveMark.hpp --- a/src/share/vm/gc_implementation/shared/isGCActiveMark.hpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/gc_implementation/shared/isGCActiveMark.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -25,9 +25,10 @@ #ifndef SHARE_VM_GC_IMPLEMENTATION_SHARED_ISGCACTIVEMARK_HPP #define SHARE_VM_GC_IMPLEMENTATION_SHARED_ISGCACTIVEMARK_HPP -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/parallelScavenge/parallelScavengeHeap.hpp" -#endif +#endif // INCLUDE_ALL_GCS // This class provides a method for block structured setting of the // _is_gc_active state without requiring accessors in CollectedHeap diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/gc_implementation/shared/markSweep.inline.hpp --- a/src/share/vm/gc_implementation/shared/markSweep.inline.hpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/gc_implementation/shared/markSweep.inline.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -28,9 +28,10 @@ #include "gc_implementation/shared/markSweep.hpp" #include "gc_interface/collectedHeap.hpp" #include "utilities/stack.inline.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/parallelScavenge/psParallelCompact.hpp" -#endif +#endif // INCLUDE_ALL_GCS inline void MarkSweep::mark_object(oop obj) { // some marks may contain information we need to preserve so we store them away diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/gc_implementation/shared/mutableNUMASpace.hpp --- a/src/share/vm/gc_implementation/shared/mutableNUMASpace.hpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/gc_implementation/shared/mutableNUMASpace.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -25,10 +25,11 @@ #ifndef SHARE_VM_GC_IMPLEMENTATION_SHARED_MUTABLENUMASPACE_HPP #define SHARE_VM_GC_IMPLEMENTATION_SHARED_MUTABLENUMASPACE_HPP -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/shared/gcUtil.hpp" #include "gc_implementation/shared/mutableSpace.hpp" -#endif +#endif // INCLUDE_ALL_GCS /* * The NUMA-aware allocator (MutableNUMASpace) is basically a modification diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/gc_implementation/shared/mutableSpace.cpp --- a/src/share/vm/gc_implementation/shared/mutableSpace.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/gc_implementation/shared/mutableSpace.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -23,13 +23,14 @@ */ #include "precompiled.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/shared/mutableSpace.hpp" #include "gc_implementation/shared/spaceDecorator.hpp" #include "oops/oop.inline.hpp" #include "runtime/safepoint.hpp" #include "runtime/thread.hpp" -#endif +#endif // INCLUDE_ALL_GCS MutableSpace::MutableSpace(size_t alignment): ImmutableSpace(), _top(NULL), _alignment(alignment) { assert(MutableSpace::alignment() >= 0 && diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/gc_implementation/shared/spaceCounters.cpp --- a/src/share/vm/gc_implementation/shared/spaceCounters.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/gc_implementation/shared/spaceCounters.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -23,10 +23,11 @@ */ #include "precompiled.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/shared/spaceCounters.hpp" #include "memory/resourceArea.hpp" -#endif +#endif // INCLUDE_ALL_GCS SpaceCounters::SpaceCounters(const char* name, int ordinal, size_t max_size, MutableSpace* m, GenerationCounters* gc) : diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/gc_implementation/shared/spaceCounters.hpp --- a/src/share/vm/gc_implementation/shared/spaceCounters.hpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/gc_implementation/shared/spaceCounters.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -25,12 +25,13 @@ #ifndef SHARE_VM_GC_IMPLEMENTATION_SHARED_SPACECOUNTERS_HPP #define SHARE_VM_GC_IMPLEMENTATION_SHARED_SPACECOUNTERS_HPP -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/shared/generationCounters.hpp" #include "gc_implementation/shared/immutableSpace.hpp" #include "gc_implementation/shared/mutableSpace.hpp" #include "runtime/perfData.hpp" -#endif +#endif // INCLUDE_ALL_GCS // A SpaceCounter is a holder class for performance counters // that track a space; diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/gc_implementation/shared/vmGCOperations.cpp --- a/src/share/vm/gc_implementation/shared/vmGCOperations.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/gc_implementation/shared/vmGCOperations.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,9 +36,10 @@ #include "runtime/interfaceSupport.hpp" #include "utilities/dtrace.hpp" #include "utilities/preserveException.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/g1/g1CollectedHeap.inline.hpp" -#endif +#endif // INCLUDE_ALL_GCS #ifndef USDT2 HS_DTRACE_PROBE_DECL1(hotspot, gc__begin, bool); @@ -167,7 +168,9 @@ ch->collect_as_vm_thread(GCCause::_heap_inspection); } } - HeapInspection::heap_inspection(_out, _need_prologue /* need_prologue */); + HeapInspection inspect(_csv_format, _print_help, _print_class_stats, + _columns); + inspect.heap_inspection(_out, _need_prologue /* need_prologue */); } diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/gc_implementation/shared/vmGCOperations.hpp --- a/src/share/vm/gc_implementation/shared/vmGCOperations.hpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/gc_implementation/shared/vmGCOperations.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -130,6 +130,10 @@ outputStream* _out; bool _full_gc; bool _need_prologue; + bool _csv_format; // "comma separated values" format for spreadsheet. + bool _print_help; + bool _print_class_stats; + const char* _columns; public: VM_GC_HeapInspection(outputStream* out, bool request_full_gc, bool need_prologue) : @@ -140,6 +144,10 @@ _out = out; _full_gc = request_full_gc; _need_prologue = need_prologue; + _csv_format = false; + _print_help = false; + _print_class_stats = false; + _columns = NULL; } ~VM_GC_HeapInspection() {} @@ -147,6 +155,10 @@ virtual bool skip_operation() const; virtual bool doit_prologue(); virtual void doit(); + void set_csv_format(bool value) {_csv_format = value;} + void set_print_help(bool value) {_print_help = value;} + void set_print_class_stats(bool value) {_print_class_stats = value;} + void set_columns(const char* value) {_columns = value;} }; diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/interpreter/bytecodeInterpreter.cpp --- a/src/share/vm/interpreter/bytecodeInterpreter.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/interpreter/bytecodeInterpreter.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -3099,9 +3099,9 @@ tty->print_cr("&native_fresult: " INTPTR_FORMAT, (uintptr_t) &this->_native_fresult); tty->print_cr("native_lresult: " INTPTR_FORMAT, (uintptr_t) this->_native_lresult); #endif -#if defined(IA64) && !defined(ZERO) +#if !defined(ZERO) tty->print_cr("last_Java_fp: " INTPTR_FORMAT, (uintptr_t) this->_last_Java_fp); -#endif // IA64 && !ZERO +#endif // !ZERO tty->print_cr("self_link: " INTPTR_FORMAT, (uintptr_t) this->_self_link); } diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/interpreter/bytecodeTracer.cpp --- a/src/share/vm/interpreter/bytecodeTracer.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/interpreter/bytecodeTracer.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -335,9 +335,6 @@ st->print_cr(" %s", constants->resolved_klass_at(i)->external_name()); } else if (tag.is_unresolved_klass()) { st->print_cr(" ", i); - } else if (tag.is_object()) { - st->print(" "); - print_oop(constants->object_at(i), st); } else if (tag.is_method_type()) { int i2 = constants->method_type_index_at(i); st->print(" %d", i2); diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/interpreter/linkResolver.cpp --- a/src/share/vm/interpreter/linkResolver.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/interpreter/linkResolver.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1241,7 +1241,6 @@ void LinkResolver::resolve_invokedynamic(CallInfo& result, constantPoolHandle pool, int index, TRAPS) { assert(EnableInvokeDynamic, ""); - pool->set_invokedynamic(); // mark header to flag active call sites //resolve_pool(, method_name, method_signature, current_klass, pool, index, CHECK); Symbol* method_name = pool->name_ref_at(index); diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/interpreter/rewriter.cpp --- a/src/share/vm/interpreter/rewriter.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/interpreter/rewriter.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -48,7 +48,6 @@ add_cp_cache_entry(i); break; case JVM_CONSTANT_String: - case JVM_CONSTANT_Object: case JVM_CONSTANT_MethodHandle : // fall through case JVM_CONSTANT_MethodType : // fall through add_resolved_references_entry(i); @@ -240,7 +239,7 @@ address p = bcp + offset; int cp_index = is_wide ? Bytes::get_Java_u2(p) : (u1)(*p); constantTag tag = _pool->tag_at(cp_index).value(); - if (tag.is_method_handle() || tag.is_method_type() || tag.is_string() || tag.is_object()) { + if (tag.is_method_handle() || tag.is_method_type() || tag.is_string()) { int ref_index = cp_entry_to_resolved_references(cp_index); if (is_wide) { (*bcp) = Bytecodes::_fast_aldc_w; diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/memory/allocation.hpp --- a/src/share/vm/memory/allocation.hpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/memory/allocation.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -148,9 +148,10 @@ mtChunk = 0x0B00, // chunk that holds content of arenas mtJavaHeap = 0x0C00, // Java heap mtClassShared = 0x0D00, // class data sharing - mt_number_of_types = 0x000D, // number of memory types (mtDontTrack + mtTest = 0x0E00, // Test type for verifying NMT + mt_number_of_types = 0x000E, // number of memory types (mtDontTrack // is not included as validate type) - mtDontTrack = 0x0E00, // memory we do not or cannot track + mtDontTrack = 0x0F00, // memory we do not or cannot track mt_masks = 0x7F00, // object type mask diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/memory/binaryTreeDictionary.cpp --- a/src/share/vm/memory/binaryTreeDictionary.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/memory/binaryTreeDictionary.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -23,6 +23,7 @@ */ #include "precompiled.hpp" +#include "utilities/macros.hpp" #include "gc_implementation/shared/allocationStats.hpp" #include "memory/binaryTreeDictionary.hpp" #include "memory/freeList.hpp" @@ -31,12 +32,13 @@ #include "memory/metachunk.hpp" #include "runtime/globals.hpp" #include "utilities/ostream.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/concurrentMarkSweep/adaptiveFreeList.hpp" #include "gc_implementation/concurrentMarkSweep/freeChunk.hpp" #include "gc_implementation/shared/spaceDecorator.hpp" #include "gc_implementation/concurrentMarkSweep/freeChunk.hpp" -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS //////////////////////////////////////////////////////////////////////////////// // A binary tree based search structure for free blocks. @@ -118,7 +120,7 @@ } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS // Specialize for AdaptiveFreeList which tries to avoid // splitting a chunk of a size that is under populated in favor of // an over populated size. The general get_better_list() just returns @@ -160,7 +162,7 @@ } return curTL; } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS template class FreeList_t> TreeList* @@ -871,9 +873,9 @@ template class FreeList_t> void BinaryTreeDictionary::dict_census_update(size_t size, bool split, bool birth){} -#ifndef SERIALGC +#if INCLUDE_ALL_GCS template <> -void BinaryTreeDictionary::dict_census_update(size_t size, bool split, bool birth){ +void AFLBinaryTreeDictionary::dict_census_update(size_t size, bool split, bool birth){ TreeList* nd = find_list(size); if (nd) { if (split) { @@ -900,7 +902,7 @@ // This is a birth associated with a LinAB. The chunk // for the LinAB is not in the dictionary. } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS template class FreeList_t> bool BinaryTreeDictionary::coal_dict_over_populated(size_t size) { @@ -909,9 +911,9 @@ return true; } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS template <> -bool BinaryTreeDictionary::coal_dict_over_populated(size_t size) { +bool AFLBinaryTreeDictionary::coal_dict_over_populated(size_t size) { if (FLSAlwaysCoalesceLarge) return true; TreeList* list_of_size = find_list(size); @@ -919,7 +921,7 @@ return list_of_size == NULL || list_of_size->coal_desired() <= 0 || list_of_size->count() > list_of_size->coal_desired(); } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS // Closures for walking the binary tree. // do_list() walks the free list in a node applying the closure @@ -979,7 +981,7 @@ void do_list(FreeList* fl) {} -#ifndef SERIALGC +#if INCLUDE_ALL_GCS void do_list(AdaptiveFreeList* fl) { double coalSurplusPercent = _percentage; fl->compute_desired(_inter_sweep_current, _inter_sweep_estimate, _intra_sweep_estimate); @@ -987,7 +989,7 @@ fl->set_before_sweep(fl->count()); fl->set_bfr_surp(fl->surplus()); } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS }; // Used to search the tree until a condition is met. @@ -1134,13 +1136,13 @@ setTreeSurplusClosure(double v) { percentage = v; } void do_list(FreeList* fl) {} -#ifndef SERIALGC +#if INCLUDE_ALL_GCS void do_list(AdaptiveFreeList* fl) { double splitSurplusPercent = percentage; fl->set_surplus(fl->count() - (ssize_t)((double)fl->desired() * splitSurplusPercent)); } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS }; template class FreeList_t> @@ -1157,7 +1159,7 @@ setTreeHintsClosure(size_t v) { hint = v; } void do_list(FreeList* fl) {} -#ifndef SERIALGC +#if INCLUDE_ALL_GCS void do_list(AdaptiveFreeList* fl) { fl->set_hint(hint); assert(fl->hint() == 0 || fl->hint() > fl->size(), @@ -1166,7 +1168,7 @@ hint = fl->size(); } } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS }; template class FreeList_t> @@ -1180,7 +1182,7 @@ class clearTreeCensusClosure : public AscendTreeCensusClosure { void do_list(FreeList* fl) {} -#ifndef SERIALGC +#if INCLUDE_ALL_GCS void do_list(AdaptiveFreeList* fl) { fl->set_prev_sweep(fl->count()); fl->set_coal_births(0); @@ -1188,7 +1190,7 @@ fl->set_split_births(0); fl->set_split_deaths(0); } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS }; template class FreeList_t> @@ -1252,7 +1254,7 @@ total()->set_count( total()->count() + fl->count() ); } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS void do_list(AdaptiveFreeList* fl) { if (++_print_line >= 40) { FreeList_t::print_labels_on(gclog_or_tty, "size"); @@ -1271,7 +1273,7 @@ total()->set_split_births(total()->split_births() + fl->split_births()); total()->set_split_deaths(total()->split_deaths() + fl->split_deaths()); } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS }; template class FreeList_t> @@ -1286,9 +1288,9 @@ FreeList_t::print_labels_on(gclog_or_tty, " "); } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS template <> -void BinaryTreeDictionary::print_dict_census(void) const { +void AFLBinaryTreeDictionary::print_dict_census(void) const { gclog_or_tty->print("\nBinaryTree\n"); AdaptiveFreeList::print_labels_on(gclog_or_tty, "size"); @@ -1308,7 +1310,7 @@ (double)(total->desired() - total->count()) /(total->desired() != 0 ? (double)total->desired() : 1.0)); } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS template class FreeList_t> class PrintFreeListsClosure : public AscendTreeCensusClosure { @@ -1414,10 +1416,10 @@ template class TreeChunk; -#ifndef SERIALGC +#if INCLUDE_ALL_GCS // Explicitly instantiate these types for FreeChunk. template class TreeList; template class BinaryTreeDictionary; template class TreeChunk; -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/memory/binaryTreeDictionary.hpp --- a/src/share/vm/memory/binaryTreeDictionary.hpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/memory/binaryTreeDictionary.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -43,6 +43,10 @@ template class FreeList_t> class DescendTreeCensusClosure; template class FreeList_t> class DescendTreeSearchClosure; +class FreeChunk; +template class AdaptiveFreeList; +typedef BinaryTreeDictionary AFLBinaryTreeDictionary; + template class FreeList_t> class TreeList : public FreeList_t { friend class TreeChunk; diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/memory/cardTableModRefBS.cpp --- a/src/share/vm/memory/cardTableModRefBS.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/memory/cardTableModRefBS.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -34,6 +34,7 @@ #include "runtime/mutexLocker.hpp" #include "runtime/virtualspace.hpp" #include "services/memTracker.hpp" +#include "utilities/macros.hpp" #ifdef COMPILER1 #include "c1/c1_LIR.hpp" #include "c1/c1_LIRGenerator.hpp" @@ -499,13 +500,13 @@ int n_threads = SharedHeap::heap()->n_par_threads(); bool is_par = n_threads > 0; if (is_par) { -#ifndef SERIALGC +#if INCLUDE_ALL_GCS assert(SharedHeap::heap()->n_par_threads() == SharedHeap::heap()->workers()->active_workers(), "Mismatch"); non_clean_card_iterate_parallel_work(sp, mr, cl, ct, n_threads); -#else // SERIALGC +#else // INCLUDE_ALL_GCS fatal("Parallel gc not supported here."); -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS } else { // We do not call the non_clean_card_iterate_serial() version below because // we want to clear the cards (which non_clean_card_iterate_serial() does not diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/memory/cardTableRS.cpp --- a/src/share/vm/memory/cardTableRS.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/memory/cardTableRS.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -31,10 +31,11 @@ #include "oops/oop.inline.hpp" #include "runtime/java.hpp" #include "runtime/os.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/g1/concurrentMark.hpp" #include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp" -#endif +#endif // INCLUDE_ALL_GCS CardTableRS::CardTableRS(MemRegion whole_heap, int max_covered_regions) : @@ -42,7 +43,7 @@ _cur_youngergen_card_val(youngergenP1_card), _regions_to_iterate(max_covered_regions - 1) { -#ifndef SERIALGC +#if INCLUDE_ALL_GCS if (UseG1GC) { _ct_bs = new G1SATBCardTableLoggingModRefBS(whole_heap, max_covered_regions); diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/memory/collectorPolicy.cpp --- a/src/share/vm/memory/collectorPolicy.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/memory/collectorPolicy.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -39,10 +39,11 @@ #include "runtime/java.hpp" #include "runtime/thread.inline.hpp" #include "runtime/vmThread.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/concurrentMarkSweep/cmsAdaptiveSizePolicy.hpp" #include "gc_implementation/concurrentMarkSweep/cmsGCAdaptivePolicyCounters.hpp" -#endif +#endif // INCLUDE_ALL_GCS // CollectorPolicy methods. @@ -167,11 +168,11 @@ void GenCollectorPolicy::initialize_size_policy(size_t init_eden_size, size_t init_promo_size, size_t init_survivor_size) { - const double max_gc_minor_pause_sec = ((double) MaxGCMinorPauseMillis)/1000.0; + const double max_gc_pause_sec = ((double) MaxGCPauseMillis)/1000.0; _size_policy = new AdaptiveSizePolicy(init_eden_size, init_promo_size, init_survivor_size, - max_gc_minor_pause_sec, + max_gc_pause_sec, GCTimeRatio); } @@ -235,6 +236,18 @@ if (NewSize + OldSize > MaxHeapSize) { MaxHeapSize = NewSize + OldSize; } + + if (FLAG_IS_CMDLINE(OldSize) && FLAG_IS_DEFAULT(NewSize)) { + // NewRatio will be used later to set the young generation size so we use + // it to calculate how big the heap should be based on the requested OldSize + // and NewRatio. + assert(NewRatio > 0, "NewRatio should have been set up earlier"); + size_t calculated_heapsize = (OldSize / NewRatio) * (NewRatio + 1); + + calculated_heapsize = align_size_up(calculated_heapsize, max_alignment()); + MaxHeapSize = calculated_heapsize; + InitialHeapSize = calculated_heapsize; + } MaxHeapSize = align_size_up(MaxHeapSize, max_alignment()); always_do_update_barrier = UseConcMarkSweepGC; @@ -384,14 +397,15 @@ // keeping it simple also seems a worthwhile goal. bool TwoGenerationCollectorPolicy::adjust_gen0_sizes(size_t* gen0_size_ptr, size_t* gen1_size_ptr, - size_t heap_size, - size_t min_gen0_size) { + const size_t heap_size, + const size_t min_gen1_size) { bool result = false; + if ((*gen1_size_ptr + *gen0_size_ptr) > heap_size) { - if (((*gen0_size_ptr + OldSize) > heap_size) && - (heap_size - min_gen0_size) >= min_alignment()) { - // Adjust gen0 down to accomodate OldSize - *gen0_size_ptr = heap_size - min_gen0_size; + if ((heap_size < (*gen0_size_ptr + min_gen1_size)) && + (heap_size >= min_gen1_size + min_alignment())) { + // Adjust gen0 down to accommodate min_gen1_size + *gen0_size_ptr = heap_size - min_gen1_size; *gen0_size_ptr = MAX2((uintx)align_size_down(*gen0_size_ptr, min_alignment()), min_alignment()); diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/memory/collectorPolicy.hpp --- a/src/share/vm/memory/collectorPolicy.hpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/memory/collectorPolicy.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,6 +29,7 @@ #include "memory/barrierSet.hpp" #include "memory/generationSpec.hpp" #include "memory/genRemSet.hpp" +#include "utilities/macros.hpp" // This class (or more correctly, subtypes of this class) // are used to define global garbage collector attributes. @@ -48,10 +49,10 @@ class GenCollectorPolicy; class TwoGenerationCollectorPolicy; class AdaptiveSizePolicy; -#ifndef SERIALGC +#if INCLUDE_ALL_GCS class ConcurrentMarkSweepPolicy; class G1CollectorPolicy; -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS class GCPolicyCounters; class MarkSweepPolicy; @@ -134,21 +135,21 @@ virtual GenCollectorPolicy* as_generation_policy() { return NULL; } virtual TwoGenerationCollectorPolicy* as_two_generation_policy() { return NULL; } virtual MarkSweepPolicy* as_mark_sweep_policy() { return NULL; } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS virtual ConcurrentMarkSweepPolicy* as_concurrent_mark_sweep_policy() { return NULL; } virtual G1CollectorPolicy* as_g1_policy() { return NULL; } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS // Note that these are not virtual. bool is_generation_policy() { return as_generation_policy() != NULL; } bool is_two_generation_policy() { return as_two_generation_policy() != NULL; } bool is_mark_sweep_policy() { return as_mark_sweep_policy() != NULL; } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS bool is_concurrent_mark_sweep_policy() { return as_concurrent_mark_sweep_policy() != NULL; } bool is_g1_policy() { return as_g1_policy() != NULL; } -#else // SERIALGC +#else // INCLUDE_ALL_GCS bool is_concurrent_mark_sweep_policy() { return false; } bool is_g1_policy() { return false; } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS virtual BarrierSet::Name barrier_set_name() = 0; @@ -321,7 +322,7 @@ // Returns true is gen0 sizes were adjusted bool adjust_gen0_sizes(size_t* gen0_size_ptr, size_t* gen1_size_ptr, - size_t heap_size, size_t min_gen1_size); + const size_t heap_size, const size_t min_gen1_size); }; class MarkSweepPolicy : public TwoGenerationCollectorPolicy { diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/memory/filemap.cpp --- a/src/share/vm/memory/filemap.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/memory/filemap.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -210,13 +210,14 @@ tty->print_cr(" %s", _full_path); } - // Remove the existing file in case another process has it open. +#ifdef _WINDOWS // On Windows, need WRITE permission to remove the file. + chmod(_full_path, _S_IREAD | _S_IWRITE); +#endif + + // Use remove() to delete the existing file because, on Unix, this will + // allow processes that have it open continued access to the file. remove(_full_path); -#ifdef _WINDOWS // if 0444 is used on Windows, then remove() will fail. - int fd = open(_full_path, O_RDWR | O_CREAT | O_TRUNC | O_BINARY, 0744); -#else int fd = open(_full_path, O_RDWR | O_CREAT | O_TRUNC | O_BINARY, 0444); -#endif if (fd < 0) { fail_stop("Unable to create shared archive file %s.", _full_path); } diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/memory/freeBlockDictionary.cpp --- a/src/share/vm/memory/freeBlockDictionary.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/memory/freeBlockDictionary.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -23,13 +23,15 @@ */ #include "precompiled.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/concurrentMarkSweep/freeChunk.hpp" -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS #include "memory/freeBlockDictionary.hpp" #include "memory/metablock.hpp" #include "memory/metachunk.hpp" #include "runtime/thread.inline.hpp" +#include "utilities/macros.hpp" #ifndef PRODUCT template Mutex* FreeBlockDictionary::par_lock() const { @@ -56,7 +58,7 @@ template class FreeBlockDictionary; template class FreeBlockDictionary; -#ifndef SERIALGC +#if INCLUDE_ALL_GCS // Explicitly instantiate for FreeChunk template class FreeBlockDictionary; -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/memory/freeList.cpp --- a/src/share/vm/memory/freeList.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/memory/freeList.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -31,10 +31,11 @@ #include "runtime/globals.hpp" #include "runtime/mutex.hpp" #include "runtime/vmThread.hpp" +#include "utilities/macros.hpp" -#ifndef SERIALGC +#if INCLUDE_ALL_GCS #include "gc_implementation/concurrentMarkSweep/freeChunk.hpp" -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS // Free list. A FreeList is used to access a linked list of chunks // of space in the heap. The head and tail are maintained so that @@ -341,6 +342,6 @@ template class FreeList; template class FreeList; -#ifndef SERIALGC +#if INCLUDE_ALL_GCS template class FreeList; -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/memory/genCollectedHeap.cpp --- a/src/share/vm/memory/genCollectedHeap.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/memory/genCollectedHeap.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -51,10 +51,11 @@ #include "services/memoryService.hpp" #include "utilities/vmError.hpp" #include "utilities/workgroup.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.hpp" #include "gc_implementation/concurrentMarkSweep/vmCMSOperations.hpp" -#endif +#endif // INCLUDE_ALL_GCS GenCollectedHeap* GenCollectedHeap::_gch; NOT_PRODUCT(size_t GenCollectedHeap::_skip_header_HeapWords = 0;) @@ -141,14 +142,14 @@ } clear_incremental_collection_failed(); -#ifndef SERIALGC +#if INCLUDE_ALL_GCS // If we are running CMS, create the collector responsible // for collecting the CMS generations. if (collector_policy()->is_concurrent_mark_sweep_policy()) { bool success = create_cms_collector(); if (!success) return JNI_ENOMEM; } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS return JNI_OK; } @@ -686,12 +687,12 @@ void GenCollectedHeap::collect(GCCause::Cause cause) { if (should_do_concurrent_full_gc(cause)) { -#ifndef SERIALGC +#if INCLUDE_ALL_GCS // mostly concurrent full collection collect_mostly_concurrent(cause); -#else // SERIALGC +#else // INCLUDE_ALL_GCS ShouldNotReachHere(); -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS } else { #ifdef ASSERT if (cause == GCCause::_scavenge_alot) { @@ -736,7 +737,7 @@ } } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS bool GenCollectedHeap::create_cms_collector() { assert(((_gens[1]->kind() == Generation::ConcurrentMarkSweep) || @@ -772,7 +773,7 @@ VMThread::execute(&op); } } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS void GenCollectedHeap::do_full_collection(bool clear_all_soft_refs) { do_full_collection(clear_all_soft_refs, _n_gens - 1); @@ -1116,22 +1117,22 @@ if (workers() != NULL) { workers()->threads_do(tc); } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS if (UseConcMarkSweepGC) { ConcurrentMarkSweepThread::threads_do(tc); } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS } void GenCollectedHeap::print_gc_threads_on(outputStream* st) const { -#ifndef SERIALGC +#if INCLUDE_ALL_GCS if (UseParNewGC) { workers()->print_worker_threads_on(st); } if (UseConcMarkSweepGC) { ConcurrentMarkSweepThread::print_all_on(st); } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS } void GenCollectedHeap::print_tracing_info() const { diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/memory/generationSpec.cpp --- a/src/share/vm/memory/generationSpec.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/memory/generationSpec.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -30,11 +30,12 @@ #include "memory/generationSpec.hpp" #include "memory/tenuredGeneration.hpp" #include "runtime/java.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/parNew/asParNewGeneration.hpp" #include "gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp" #include "gc_implementation/parNew/parNewGeneration.hpp" -#endif +#endif // INCLUDE_ALL_GCS Generation* GenerationSpec::init(ReservedSpace rs, int level, GenRemSet* remset) { @@ -45,7 +46,7 @@ case Generation::MarkSweepCompact: return new TenuredGeneration(rs, init_size(), level, remset); -#ifndef SERIALGC +#if INCLUDE_ALL_GCS case Generation::ParNew: return new ParNewGeneration(rs, init_size(), level); @@ -94,7 +95,7 @@ return g; } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS default: guarantee(false, "unrecognized GenerationName"); diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/memory/heapInspection.cpp --- a/src/share/vm/memory/heapInspection.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/memory/heapInspection.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,15 +23,17 @@ */ #include "precompiled.hpp" +#include "classfile/classLoaderData.hpp" #include "gc_interface/collectedHeap.hpp" #include "memory/genCollectedHeap.hpp" #include "memory/heapInspection.hpp" #include "memory/resourceArea.hpp" #include "runtime/os.hpp" #include "utilities/globalDefinitions.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/parallelScavenge/parallelScavengeHeap.hpp" -#endif +#endif // INCLUDE_ALL_GCS // HeapInspection @@ -41,12 +43,24 @@ } else if(e1->_instance_words < e2->_instance_words) { return 1; } - return 0; + // Sort alphabetically, note 'Z' < '[' < 'a', but it's better to group + // the array classes before all the instance classes. + ResourceMark rm; + const char* name1 = e1->klass()->external_name(); + const char* name2 = e2->klass()->external_name(); + bool d1 = (name1[0] == '['); + bool d2 = (name2[0] == '['); + if (d1 && !d2) { + return -1; + } else if (d2 && !d1) { + return 1; + } else { + return strcmp(name1, name2); + } } -void KlassInfoEntry::print_on(outputStream* st) const { - ResourceMark rm; - const char* name;; +const char* KlassInfoEntry::name() const { + const char* name; if (_klass->name() != NULL) { name = _klass->external_name(); } else { @@ -60,11 +74,17 @@ if (_klass == Universe::longArrayKlassObj()) name = ""; else name = ""; } + return name; +} + +void KlassInfoEntry::print_on(outputStream* st) const { + ResourceMark rm; + // simplify the formatting (ILP32 vs LP64) - always cast the numbers to 64-bit st->print_cr(INT64_FORMAT_W(13) " " UINT64_FORMAT_W(13) " %s", (jlong) _instance_count, (julong) _instance_words * HeapWordSize, - name); + name()); } KlassInfoEntry* KlassInfoBucket::lookup(Klass* const k) { @@ -101,7 +121,14 @@ } } -KlassInfoTable::KlassInfoTable(int size, HeapWord* ref) { +void KlassInfoTable::AllClassesFinder::do_klass(Klass* k) { + // This has the SIDE EFFECT of creating a KlassInfoEntry + // for , if one doesn't exist yet. + _table->lookup(k); +} + +KlassInfoTable::KlassInfoTable(int size, HeapWord* ref, + bool need_class_stats) { _size = 0; _ref = ref; _buckets = NEW_C_HEAP_ARRAY(KlassInfoBucket, size, mtInternal); @@ -110,6 +137,10 @@ for (int index = 0; index < _size; index++) { _buckets[index].initialize(); } + if (need_class_stats) { + AllClassesFinder finder(this); + ClassLoaderDataGraph::classes_do(&finder); + } } } @@ -165,7 +196,8 @@ return (*e1)->compare(*e1,*e2); } -KlassInfoHisto::KlassInfoHisto(const char* title, int estimatedCount) : +KlassInfoHisto::KlassInfoHisto(KlassInfoTable* cit, const char* title, int estimatedCount) : + _cit(cit), _title(title) { _elements = new (ResourceObj::C_HEAP, mtInternal) GrowableArray(estimatedCount,true); } @@ -196,9 +228,205 @@ total, totalw * HeapWordSize); } -void KlassInfoHisto::print_on(outputStream* st) const { - st->print_cr("%s",title()); - print_elements(st); +#define MAKE_COL_NAME(field, name, help) #name, +#define MAKE_COL_HELP(field, name, help) help, + +static const char *name_table[] = { + HEAP_INSPECTION_COLUMNS_DO(MAKE_COL_NAME) +}; + +static const char *help_table[] = { + HEAP_INSPECTION_COLUMNS_DO(MAKE_COL_HELP) +}; + +bool KlassInfoHisto::is_selected(const char *col_name) { + if (_selected_columns == NULL) { + return true; + } + if (strcmp(_selected_columns, col_name) == 0) { + return true; + } + + const char *start = strstr(_selected_columns, col_name); + if (start == NULL) { + return false; + } + + // The following must be true, because _selected_columns != col_name + if (start > _selected_columns && start[-1] != ',') { + return false; + } + char x = start[strlen(col_name)]; + if (x != ',' && x != '\0') { + return false; + } + + return true; +} + +void KlassInfoHisto::print_title(outputStream* st, bool csv_format, + bool selected[], int width_table[], + const char *name_table[]) { + if (csv_format) { + st->print("Index,Super"); + for (int c=0; cprint(",%s", name_table[c]);} + } + st->print(",ClassName"); + } else { + st->print("Index Super"); + for (int c=0; cprint(str_fmt(width_table[c]), name_table[c]);} + } + st->print(" ClassName"); + } + + if (is_selected("ClassLoader")) { + st->print(",ClassLoader"); + } + st->cr(); +} + +void KlassInfoHisto::print_class_stats(outputStream* st, + bool csv_format, const char *columns) { + ResourceMark rm; + KlassSizeStats sz, sz_sum; + int i; + julong *col_table = (julong*)(&sz); + julong *colsum_table = (julong*)(&sz_sum); + int width_table[KlassSizeStats::_num_columns]; + bool selected[KlassSizeStats::_num_columns]; + + _selected_columns = columns; + + memset(&sz_sum, 0, sizeof(sz_sum)); + for (int c=0; clength(); i++) { + elements()->at(i)->set_index(i+1); + } + + for (int pass=1; pass<=2; pass++) { + if (pass == 2) { + print_title(st, csv_format, selected, width_table, name_table); + } + for(i=0; i < elements()->length(); i++) { + KlassInfoEntry* e = (KlassInfoEntry*)elements()->at(i); + const Klass* k = e->klass(); + + memset(&sz, 0, sizeof(sz)); + sz._inst_count = e->count(); + sz._inst_bytes = HeapWordSize * e->words(); + k->collect_statistics(&sz); + sz._total_bytes = sz._ro_bytes + sz._rw_bytes; + + if (pass == 1) { + for (int c=0; coop_is_instance()) { + Klass* super = ((InstanceKlass*)k)->java_super(); + if (super) { + KlassInfoEntry* super_e = _cit->lookup(super); + if (super_e) { + super_index = super_e->index(); + } + } + } + + if (csv_format) { + st->print("%d,%d", e->index(), super_index); + for (int c=0; cprint("," JULONG_FORMAT, col_table[c]);} + } + st->print(",%s",e->name()); + } else { + st->print("%5d %5d", e->index(), super_index); + for (int c=0; cprint(" %s", e->name()); + } + if (is_selected("ClassLoader")) { + ClassLoaderData* loader_data = k->class_loader_data(); + st->print(","); + loader_data->print_value_on(st); + } + st->cr(); + } + } + + if (pass == 1) { + for (int c=0; cprint(","); + for (int c=0; cprint("," JULONG_FORMAT, colsum_table[c]);} + } + } else { + st->print(" "); + for (int c=0; cprint(" Total"); + if (sz_sum._total_bytes > 0) { + st->cr(); + st->print(" "); + for (int c=0; cprint(str_fmt(width_table[c]), "-"); + break; + default: + { + double perc = (double)(100) * (double)(colsum_table[c]) / (double)sz_sum._total_bytes; + st->print(perc_fmt(width_table[c]), perc); + } + } + } + } + } + } + st->cr(); + + if (!csv_format) { + print_title(st, csv_format, selected, width_table, name_table); + } +} + +julong KlassInfoHisto::annotations_bytes(Array* p) const { + julong bytes = 0; + if (p != NULL) { + for (int i = 0; i < p->length(); i++) { + bytes += count_bytes_array(p->at(i)); + } + bytes += count_bytes_array(p); + } + return bytes; +} + +void KlassInfoHisto::print_histo_on(outputStream* st, bool print_stats, + bool csv_format, const char *columns) { + if (print_stats) { + print_class_stats(st, csv_format, columns); + } else { + st->print_cr("%s",title()); + print_elements(st); + } } class HistoClosure : public KlassInfoClosure { @@ -236,8 +464,26 @@ CollectedHeap* heap = Universe::heap(); bool is_shared_heap = false; + if (_print_help) { + for (int c=0; cprint("%s:\n\t", name_table[c]); + const int max_col = 60; + int col = 0; + for (const char *p = help_table[c]; *p; p++,col++) { + if (col >= max_col && *p == ' ') { + st->print("\n\t"); + col = 0; + } else { + st->print("%c", *p); + } + } + st->print_cr(".\n"); + } + return; + } + // Collect klass instance info - KlassInfoTable cit(KlassInfoTable::cit_size, ref); + KlassInfoTable cit(KlassInfoTable::cit_size, ref, _print_class_stats); if (!cit.allocation_failed()) { // Iterate over objects in the heap RecordInstanceClosure ric(&cit); @@ -252,14 +498,14 @@ missed_count); } // Sort and print klass instance info - KlassInfoHisto histo("\n" - " num #instances #bytes class name\n" - "----------------------------------------------", - KlassInfoHisto::histo_initial_size); + const char *title = "\n" + " num #instances #bytes class name\n" + "----------------------------------------------"; + KlassInfoHisto histo(&cit, title, KlassInfoHisto::histo_initial_size); HistoClosure hc(&histo); cit.iterate(&hc); histo.sort(); - histo.print_on(st); + histo.print_histo_on(st, _print_class_stats, _csv_format, _columns); } else { st->print_cr("WARNING: Ran out of C-heap; histogram not generated"); } diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/memory/heapInspection.hpp --- a/src/share/vm/memory/heapInspection.hpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/memory/heapInspection.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,6 +27,8 @@ #include "memory/allocation.inline.hpp" #include "oops/oop.inline.hpp" +#include "oops/annotations.hpp" +#include "utilities/macros.hpp" #if INCLUDE_SERVICES @@ -44,16 +46,148 @@ // to KlassInfoEntry's and is used to sort // the entries. +#define HEAP_INSPECTION_COLUMNS_DO(f) \ + f(inst_size, InstSize, \ + "Size of each object instance of the Java class") \ + f(inst_count, InstCount, \ + "Number of object instances of the Java class") \ + f(inst_bytes, InstBytes, \ + "This is usually (InstSize * InstNum). The only exception is " \ + "java.lang.Class, whose InstBytes also includes the slots " \ + "used to store static fields. InstBytes is not counted in " \ + "ROAll, RWAll or Total") \ + f(mirror_bytes, Mirror, \ + "Size of the Klass::java_mirror() object") \ + f(klass_bytes, KlassBytes, \ + "Size of the InstanceKlass or ArrayKlass for this class. " \ + "Note that this includes VTab, ITab, OopMap") \ + f(secondary_supers_bytes, K_secondary_supers, \ + "Number of bytes used by the Klass::secondary_supers() array") \ + f(vtab_bytes, VTab, \ + "Size of the embedded vtable in InstanceKlass") \ + f(itab_bytes, ITab, \ + "Size of the embedded itable in InstanceKlass") \ + f(nonstatic_oopmap_bytes, OopMap, \ + "Size of the embedded nonstatic_oop_map in InstanceKlass") \ + f(methods_array_bytes, IK_methods, \ + "Number of bytes used by the InstanceKlass::methods() array") \ + f(method_ordering_bytes, IK_method_ordering, \ + "Number of bytes used by the InstanceKlass::method_ordering() array") \ + f(local_interfaces_bytes, IK_local_interfaces, \ + "Number of bytes used by the InstanceKlass::local_interfaces() array") \ + f(transitive_interfaces_bytes, IK_transitive_interfaces, \ + "Number of bytes used by the InstanceKlass::transitive_interfaces() array") \ + f(fields_bytes, IK_fields, \ + "Number of bytes used by the InstanceKlass::fields() array") \ + f(inner_classes_bytes, IK_inner_classes, \ + "Number of bytes used by the InstanceKlass::inner_classes() array") \ + f(signers_bytes, IK_signers, \ + "Number of bytes used by the InstanceKlass::singers() array") \ + f(class_annotations_bytes, class_annotations, \ + "Size of class annotations") \ + f(class_type_annotations_bytes, class_type_annotations, \ + "Size of class type annotations") \ + f(fields_annotations_bytes, fields_annotations, \ + "Size of field annotations") \ + f(fields_type_annotations_bytes, fields_type_annotations, \ + "Size of field type annotations") \ + f(methods_annotations_bytes, methods_annotations, \ + "Size of method annotations") \ + f(methods_parameter_annotations_bytes, methods_parameter_annotations, \ + "Size of method parameter annotations") \ + f(methods_type_annotations_bytes, methods_type_annotations, \ + "Size of methods type annotations") \ + f(methods_default_annotations_bytes, methods_default_annotations, \ + "Size of methods default annotations") \ + f(annotations_bytes, annotations, \ + "Size of all annotations") \ + f(cp_bytes, Cp, \ + "Size of InstanceKlass::constants()") \ + f(cp_tags_bytes, CpTags, \ + "Size of InstanceKlass::constants()->tags()") \ + f(cp_cache_bytes, CpCache, \ + "Size of InstanceKlass::constants()->cache()") \ + f(cp_operands_bytes, CpOperands, \ + "Size of InstanceKlass::constants()->operands()") \ + f(cp_refmap_bytes, CpRefMap, \ + "Size of InstanceKlass::constants()->reference_map()") \ + f(cp_all_bytes, CpAll, \ + "Sum of Cp + CpTags + CpCache + CpOperands + CpRefMap") \ + f(method_count, MethodCount, \ + "Number of methods in this class") \ + f(method_bytes, MethodBytes, \ + "Size of the Method object") \ + f(const_method_bytes, ConstMethod, \ + "Size of the ConstMethod object") \ + f(method_data_bytes, MethodData, \ + "Size of the MethodData object") \ + f(stackmap_bytes, StackMap, \ + "Size of the stackmap_data") \ + f(bytecode_bytes, Bytecodes, \ + "Of the MethodBytes column, how much are the space taken up by bytecodes") \ + f(method_all_bytes, MethodAll, \ + "Sum of MethodBytes + Constmethod + Stackmap + Methoddata") \ + f(ro_bytes, ROAll, \ + "Size of all class meta data that could (potentially) be placed " \ + "in read-only memory. (This could change with CDS design)") \ + f(rw_bytes, RWAll, \ + "Size of all class meta data that must be placed in read/write " \ + "memory. (This could change with CDS design) ") \ + f(total_bytes, Total, \ + "ROAll + RWAll. Note that this does NOT include InstBytes.") + +// Size statistics for a Klass - filled in by Klass::collect_statistics() +class KlassSizeStats { +public: +#define COUNT_KLASS_SIZE_STATS_FIELD(field, name, help) _index_ ## field, +#define DECLARE_KLASS_SIZE_STATS_FIELD(field, name, help) julong _ ## field; + + enum { + HEAP_INSPECTION_COLUMNS_DO(COUNT_KLASS_SIZE_STATS_FIELD) + _num_columns + }; + + HEAP_INSPECTION_COLUMNS_DO(DECLARE_KLASS_SIZE_STATS_FIELD) + + static int count(oop x) { + return (HeapWordSize * ((x) ? (x)->size() : 0)); + } + + static int count_array(objArrayOop x) { + return (HeapWordSize * ((x) ? (x)->size() : 0)); + } + + template static int count(T* x) { + return (HeapWordSize * ((x) ? (x)->size() : 0)); + } + + template static int count_array(T* x) { + if (x == NULL) { + return 0; + } + if (x->length() == 0) { + // This is a shared array, e.g., Universe::the_empty_int_array(). Don't + // count it to avoid double-counting. + return 0; + } + return HeapWordSize * x->size(); + } +}; + + + + class KlassInfoEntry: public CHeapObj { private: KlassInfoEntry* _next; Klass* _klass; long _instance_count; size_t _instance_words; + long _index; public: KlassInfoEntry(Klass* k, KlassInfoEntry* next) : - _klass(k), _instance_count(0), _instance_words(0), _next(next) + _klass(k), _instance_count(0), _instance_words(0), _next(next), _index(-1) {} KlassInfoEntry* next() { return _next; } bool is_equal(Klass* k) { return k == _klass; } @@ -62,8 +196,11 @@ void set_count(long ct) { _instance_count = ct; } size_t words() { return _instance_words; } void set_words(size_t wds) { _instance_words = wds; } + void set_index(long index) { _index = index; } + long index() { return _index; } int compare(KlassInfoEntry* e1, KlassInfoEntry* e2); void print_on(outputStream* st) const; + const char* name() const; }; class KlassInfoClosure: public StackObj { @@ -95,45 +232,132 @@ KlassInfoBucket* _buckets; uint hash(Klass* p); - KlassInfoEntry* lookup(Klass* const k); + KlassInfoEntry* lookup(Klass* const k); // allocates if not found! + + class AllClassesFinder : public KlassClosure { + KlassInfoTable *_table; + public: + AllClassesFinder(KlassInfoTable* table) : _table(table) {} + virtual void do_klass(Klass* k); + }; public: // Table size enum { cit_size = 20011 }; - KlassInfoTable(int size, HeapWord* ref); + KlassInfoTable(int size, HeapWord* ref, bool need_class_stats); ~KlassInfoTable(); bool record_instance(const oop obj); void iterate(KlassInfoClosure* cic); bool allocation_failed() { return _buckets == NULL; } + + friend class KlassInfoHisto; }; class KlassInfoHisto : public StackObj { private: + KlassInfoTable *_cit; GrowableArray* _elements; GrowableArray* elements() const { return _elements; } const char* _title; const char* title() const { return _title; } static int sort_helper(KlassInfoEntry** e1, KlassInfoEntry** e2); void print_elements(outputStream* st) const; + void print_class_stats(outputStream* st, bool csv_format, const char *columns); + julong annotations_bytes(Array* p) const; + const char *_selected_columns; + bool is_selected(const char *col_name); + void print_title(outputStream* st, bool csv_format, + bool selected_columns_table[], int width_table[], + const char *name_table[]); + + template static int count_bytes(T* x) { + return (HeapWordSize * ((x) ? (x)->size() : 0)); + } + + template static int count_bytes_array(T* x) { + if (x == NULL) { + return 0; + } + if (x->length() == 0) { + // This is a shared array, e.g., Universe::the_empty_int_array(). Don't + // count it to avoid double-counting. + return 0; + } + return HeapWordSize * x->size(); + } + + // returns a format string to print a julong with the given width. E.g, + // printf(num_fmt(6), julong(10)) would print out the number 10 with 4 + // leading spaces. + static void print_julong(outputStream* st, int width, julong n) { + int num_spaces = width - julong_width(n); + if (num_spaces > 0) { + st->print(str_fmt(num_spaces), ""); + } + st->print(JULONG_FORMAT, n); + } + + static char* perc_fmt(int width) { + static char buf[32]; + jio_snprintf(buf, sizeof(buf), "%%%d.1f%%%%", width-1); + return buf; + } + + static char* str_fmt(int width) { + static char buf[32]; + jio_snprintf(buf, sizeof(buf), "%%%ds", width); + return buf; + } + + static int julong_width(julong n) { + if (n == 0) { + return 1; + } + int w = 0; + while (n > 0) { + n /= 10; + w += 1; + } + return w; + } + + static int col_width(julong n, const char *name) { + int w = julong_width(n); + int min = (int)(strlen(name)); + if (w < min) { + w = min; + } + // add a leading space for separation. + return w + 1; + } + public: enum { histo_initial_size = 1000 }; - KlassInfoHisto(const char* title, + KlassInfoHisto(KlassInfoTable* cit, const char* title, int estimatedCount); ~KlassInfoHisto(); void add(KlassInfoEntry* cie); - void print_on(outputStream* st) const; + void print_histo_on(outputStream* st, bool print_class_stats, bool csv_format, const char *columns); void sort(); }; #endif // INCLUDE_SERVICES -class HeapInspection : public AllStatic { +class HeapInspection : public StackObj { + bool _csv_format; // "comma separated values" format for spreadsheet. + bool _print_help; + bool _print_class_stats; + const char* _columns; public: - static void heap_inspection(outputStream* st, bool need_prologue) NOT_SERVICES_RETURN; + HeapInspection(bool csv_format, bool print_help, + bool print_class_stats, const char *columns) : + _csv_format(csv_format), _print_help(print_help), + _print_class_stats(print_class_stats), _columns(columns) {} + void heap_inspection(outputStream* st, bool need_prologue) NOT_SERVICES_RETURN; static void find_instances_at_safepoint(Klass* k, GrowableArray* result) NOT_SERVICES_RETURN; }; diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/memory/metaspace.cpp --- a/src/share/vm/memory/metaspace.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/memory/metaspace.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -1064,11 +1064,11 @@ // // After the GC the compute_new_size() for MetaspaceGC is called to // resize the capacity of the metaspaces. The current implementation -// is based on the flags MinHeapFreeRatio and MaxHeapFreeRatio used +// is based on the flags MinMetaspaceFreeRatio and MaxHeapFreeRatio used // to resize the Java heap by some GC's. New flags can be implemented // if really needed. MinHeapFreeRatio is used to calculate how much // free space is desirable in the metaspace capacity to decide how much -// to increase the HWM. MaxHeapFreeRatio is used to decide how much +// to increase the HWM. MaxMetaspaceFreeRatio is used to decide how much // free space is desirable in the metaspace capacity before decreasing // the HWM. @@ -1166,7 +1166,7 @@ size_t capacity_until_GC = vsl->capacity_bytes_sum(); size_t free_after_gc = capacity_until_GC - used_after_gc; - const double minimum_free_percentage = MinHeapFreeRatio / 100.0; + const double minimum_free_percentage = MinMetaspaceFreeRatio / 100.0; const double maximum_used_percentage = 1.0 - minimum_free_percentage; const double min_tmp = used_after_gc / maximum_used_percentage; @@ -1232,8 +1232,8 @@ max_shrink_words)); // Should shrinking be considered? - if (MaxHeapFreeRatio < 100) { - const double maximum_free_percentage = MaxHeapFreeRatio / 100.0; + if (MaxMetaspaceFreeRatio < 100) { + const double maximum_free_percentage = MaxMetaspaceFreeRatio / 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)); @@ -1737,10 +1737,10 @@ *class_chunk_word_size = ClassSmallChunk; break; } - assert(chunk_word_size != 0 && class_chunk_word_size != 0, + assert(*chunk_word_size != 0 && *class_chunk_word_size != 0, err_msg("Initial chunks sizes bad: data " SIZE_FORMAT " class " SIZE_FORMAT, - chunk_word_size, class_chunk_word_size)); + *chunk_word_size, *class_chunk_word_size)); } size_t SpaceManager::sum_free_in_chunks_in_use() const { @@ -2040,7 +2040,7 @@ align_size_up(humongous_chunks->word_size(), HumongousChunkGranularity), err_msg("Humongous chunk size is wrong: word size " SIZE_FORMAT - " granularity " SIZE_FORMAT, + " granularity %d", humongous_chunks->word_size(), HumongousChunkGranularity)); Metachunk* next_humongous_chunks = humongous_chunks->next(); chunk_manager->humongous_dictionary()->return_chunk(humongous_chunks); @@ -2264,7 +2264,8 @@ } MutexLockerEx cl(lock(), Mutex::_no_safepoint_check_flag); assert(allocation_total() == sum_used_in_chunks_in_use(), - err_msg("allocation total is not consistent %d vs %d", + err_msg("allocation total is not consistent " SIZE_FORMAT + " vs " SIZE_FORMAT, allocation_total(), sum_used_in_chunks_in_use())); } @@ -2578,7 +2579,8 @@ // argument passed in is at the top of the compressed space void Metaspace::initialize_class_space(ReservedSpace rs) { // The reserved space size may be bigger because of alignment, esp with UseLargePages - assert(rs.size() >= ClassMetaspaceSize, err_msg("%d != %d", rs.size(), ClassMetaspaceSize)); + assert(rs.size() >= ClassMetaspaceSize, + err_msg(SIZE_FORMAT " != " UINTX_FORMAT, rs.size(), ClassMetaspaceSize)); _class_space_list = new VirtualSpaceList(rs); } diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/memory/space.cpp --- a/src/share/vm/memory/space.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/memory/space.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -40,6 +40,7 @@ #include "runtime/safepoint.hpp" #include "utilities/copy.hpp" #include "utilities/globalDefinitions.hpp" +#include "utilities/macros.hpp" void SpaceMemRegionOopsIterClosure::do_oop(oop* p) { SpaceMemRegionOopsIterClosure::do_oop_work(p); } void SpaceMemRegionOopsIterClosure::do_oop(narrowOop* p) { SpaceMemRegionOopsIterClosure::do_oop_work(p); } @@ -658,7 +659,7 @@ } } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS #define ContigSpace_PAR_OOP_ITERATE_DEFN(OopClosureType, nv_suffix) \ \ void ContiguousSpace::par_oop_iterate(MemRegion mr, OopClosureType* blk) {\ @@ -673,7 +674,7 @@ ALL_PAR_OOP_ITERATE_CLOSURES(ContigSpace_PAR_OOP_ITERATE_DEFN) #undef ContigSpace_PAR_OOP_ITERATE_DEFN -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS void ContiguousSpace::oop_iterate(ExtendedOopClosure* blk) { if (is_empty()) return; diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/memory/space.hpp --- a/src/share/vm/memory/space.hpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/memory/space.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -34,6 +34,7 @@ #include "oops/markOop.hpp" #include "runtime/mutexLocker.hpp" #include "runtime/prefetch.hpp" +#include "utilities/macros.hpp" #include "utilities/workgroup.hpp" #ifdef TARGET_OS_FAMILY_linux # include "os_linux.inline.hpp" @@ -884,14 +885,14 @@ } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS // In support of parallel oop_iterate. #define ContigSpace_PAR_OOP_ITERATE_DECL(OopClosureType, nv_suffix) \ void par_oop_iterate(MemRegion mr, OopClosureType* blk); ALL_PAR_OOP_ITERATE_CLOSURES(ContigSpace_PAR_OOP_ITERATE_DECL) #undef ContigSpace_PAR_OOP_ITERATE_DECL -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS // Compaction support virtual void reset_after_compaction() { diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/memory/specialized_oop_closures.hpp --- a/src/share/vm/memory/specialized_oop_closures.hpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/memory/specialized_oop_closures.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -26,9 +26,10 @@ #define SHARE_VM_MEMORY_SPECIALIZED_OOP_CLOSURES_HPP #include "runtime/atomic.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/g1/g1_specialized_oop_closures.hpp" -#endif +#endif // INCLUDE_ALL_GCS // The following OopClosure types get specialized versions of // "oop_oop_iterate" that invoke the closures' do_oop methods @@ -80,20 +81,20 @@ f(FastScanClosure,_nv) \ f(FilteringClosure,_nv) -#ifndef SERIALGC +#if INCLUDE_ALL_GCS #define SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_P(f) \ f(ParScanWithBarrierClosure,_nv) \ f(ParScanWithoutBarrierClosure,_nv) -#else // SERIALGC +#else // INCLUDE_ALL_GCS #define SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_P(f) -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS #define SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_1(f) \ f(NoHeaderExtendedOopClosure,_nv) \ SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_S(f) \ SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_P(f) -#ifndef SERIALGC +#if INCLUDE_ALL_GCS #define SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_2(f) \ f(MarkRefsIntoAndScanClosure,_nv) \ f(Par_MarkRefsIntoAndScanClosure,_nv) \ @@ -104,9 +105,9 @@ f(CMSKeepAliveClosure,_nv) \ f(CMSInnerParMarkAndPushClosure,_nv) \ FURTHER_SPECIALIZED_OOP_OOP_ITERATE_CLOSURES(f) -#else // SERIALGC +#else // INCLUDE_ALL_GCS #define SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_2(f) -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS // We separate these out, because sometime the general one has @@ -120,7 +121,7 @@ #define ALL_OOP_OOP_ITERATE_CLOSURES_2(f) \ SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_2(f) -#ifndef SERIALGC +#if INCLUDE_ALL_GCS // This macro applies an argument macro to all OopClosures for which we // want specialized bodies of a family of methods related to // "par_oop_iterate". The arguments to f are the same as above. @@ -136,7 +137,7 @@ #define ALL_PAR_OOP_ITERATE_CLOSURES(f) \ f(ExtendedOopClosure,_v) \ SPECIALIZED_PAR_OOP_ITERATE_CLOSURES(f) -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS // This macro applies an argument macro to all OopClosures for which we // want specialized bodies of a family of methods related to @@ -155,14 +156,14 @@ f(ScanClosure,_nv) \ f(FastScanClosure,_nv) -#ifndef SERIALGC +#if INCLUDE_ALL_GCS #define SPECIALIZED_SINCE_SAVE_MARKS_CLOSURES_YOUNG_P(f) \ f(ParScanWithBarrierClosure,_nv) \ f(ParScanWithoutBarrierClosure,_nv) \ FURTHER_SPECIALIZED_SINCE_SAVE_MARKS_CLOSURES(f) -#else // SERIALGC +#else // INCLUDE_ALL_GCS #define SPECIALIZED_SINCE_SAVE_MARKS_CLOSURES_YOUNG_P(f) -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS #define SPECIALIZED_SINCE_SAVE_MARKS_CLOSURES_YOUNG(f) \ SPECIALIZED_SINCE_SAVE_MARKS_CLOSURES_YOUNG_S(f) \ diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/memory/tenuredGeneration.cpp --- a/src/share/vm/memory/tenuredGeneration.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/memory/tenuredGeneration.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -33,6 +33,7 @@ #include "memory/tenuredGeneration.hpp" #include "oops/oop.inline.hpp" #include "runtime/java.hpp" +#include "utilities/macros.hpp" TenuredGeneration::TenuredGeneration(ReservedSpace rs, size_t initial_byte_size, int level, @@ -61,7 +62,7 @@ _space_counters = new CSpaceCounters(gen_name, 0, _virtual_space.reserved_size(), _the_space, _gen_counters); -#ifndef SERIALGC +#if INCLUDE_ALL_GCS if (UseParNewGC) { typedef ParGCAllocBufferWithBOT* ParGCAllocBufferWithBOTPtr; _alloc_buffers = NEW_C_HEAP_ARRAY(ParGCAllocBufferWithBOTPtr, @@ -77,7 +78,7 @@ } else { _alloc_buffers = NULL; } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS } @@ -339,7 +340,7 @@ } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS oop TenuredGeneration::par_promote(int thread_num, oop old, markOop m, size_t word_sz) { @@ -423,10 +424,10 @@ } } -#else // SERIALGC +#else // INCLUDE_ALL_GCS void TenuredGeneration::retire_alloc_buffers_before_full_gc() {} void TenuredGeneration::verify_alloc_buffers_clean() {} -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS bool TenuredGeneration::promotion_attempt_is_safe(size_t max_promotion_in_bytes) const { size_t available = max_contiguous_available(); diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/memory/tenuredGeneration.hpp --- a/src/share/vm/memory/tenuredGeneration.hpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/memory/tenuredGeneration.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -29,6 +29,7 @@ #include "gc_implementation/shared/gcStats.hpp" #include "gc_implementation/shared/generationCounters.hpp" #include "memory/generation.hpp" +#include "utilities/macros.hpp" // TenuredGeneration models the heap containing old (promoted/tenured) objects. @@ -45,11 +46,11 @@ size_t _capacity_at_prologue; size_t _used_at_prologue; -#ifndef SERIALGC +#if INCLUDE_ALL_GCS // To support parallel promotion: an array of parallel allocation // buffers, one per thread, initially NULL. ParGCAllocBufferWithBOT** _alloc_buffers; -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS // Retire all alloc buffers before a full GC, so that they will be // re-allocated at the start of the next young GC. @@ -93,14 +94,14 @@ size_t size, bool is_tlab); -#ifndef SERIALGC +#if INCLUDE_ALL_GCS // Overrides. virtual oop par_promote(int thread_num, oop obj, markOop m, size_t word_sz); virtual void par_promote_alloc_undo(int thread_num, HeapWord* obj, size_t word_sz); virtual void par_promote_alloc_done(int thread_num); -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS // Performance Counter support void update_counters(); diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/memory/universe.cpp --- a/src/share/vm/memory/universe.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/memory/universe.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -70,13 +70,14 @@ #include "utilities/events.hpp" #include "utilities/hashtable.inline.hpp" #include "utilities/preserveException.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/concurrentMarkSweep/cmsAdaptiveSizePolicy.hpp" #include "gc_implementation/concurrentMarkSweep/cmsCollectorPolicy.hpp" #include "gc_implementation/g1/g1CollectedHeap.inline.hpp" #include "gc_implementation/g1/g1CollectorPolicy.hpp" #include "gc_implementation/parallelScavenge/parallelScavengeHeap.hpp" -#endif +#endif // INCLUDE_ALL_GCS // Known objects Klass* Universe::_boolArrayKlassObj = NULL; @@ -144,6 +145,7 @@ NarrowPtrStruct Universe::_narrow_klass = { NULL, 0, true }; address Universe::_narrow_ptrs_base; +size_t Universe::_class_metaspace_size; void Universe::basic_type_classes_do(void f(Klass*)) { f(boolArrayKlassObj()); @@ -689,8 +691,15 @@ // Return specified base for the first request. if (!FLAG_IS_DEFAULT(HeapBaseMinAddress) && (mode == UnscaledNarrowOop)) { base = HeapBaseMinAddress; - } else if (total_size <= OopEncodingHeapMax && (mode != HeapBasedNarrowOop)) { - if (total_size <= NarrowOopHeapMax && (mode == UnscaledNarrowOop) && + + // If the total size and the metaspace size are small enough to allow + // UnscaledNarrowOop then just use UnscaledNarrowOop. + } else if ((total_size <= OopEncodingHeapMax) && (mode != HeapBasedNarrowOop) && + (!UseCompressedKlassPointers || + (((OopEncodingHeapMax - heap_size) + Universe::class_metaspace_size()) <= KlassEncodingMetaspaceMax))) { + // We don't need to check the metaspace size here because it is always smaller + // than total_size. + if ((total_size <= NarrowOopHeapMax) && (mode == UnscaledNarrowOop) && (Universe::narrow_oop_shift() == 0)) { // Use 32-bits oops without encoding and // place heap's top on the 4Gb boundary @@ -706,14 +715,24 @@ base = (OopEncodingHeapMax - heap_size); } } + + // See if ZeroBaseNarrowOop encoding will work for a heap based at + // (KlassEncodingMetaspaceMax - class_metaspace_size()). + } else if (UseCompressedKlassPointers && (mode != HeapBasedNarrowOop) && + (Universe::class_metaspace_size() + HeapBaseMinAddress <= KlassEncodingMetaspaceMax) && + (KlassEncodingMetaspaceMax + heap_size - Universe::class_metaspace_size() <= OopEncodingHeapMax)) { + base = (KlassEncodingMetaspaceMax - Universe::class_metaspace_size()); } else { - // Can't reserve below 32Gb. + // UnscaledNarrowOop encoding didn't work, and no base was found for ZeroBasedOops or + // HeapBasedNarrowOop encoding was requested. So, can't reserve below 32Gb. Universe::set_narrow_oop_shift(LogMinObjAlignmentInBytes); } + // Set narrow_oop_base and narrow_oop_use_implicit_null_checks // used in ReservedHeapSpace() constructors. // The final values will be set in initialize_heap() below. - if (base != 0 && (base + heap_size) <= OopEncodingHeapMax) { + if ((base != 0) && ((base + heap_size) <= OopEncodingHeapMax) && + (!UseCompressedKlassPointers || (base + Universe::class_metaspace_size()) <= KlassEncodingMetaspaceMax)) { // Use zero based compressed oops Universe::set_narrow_oop_base(NULL); // Don't need guard page for implicit checks in indexed @@ -740,20 +759,20 @@ jint Universe::initialize_heap() { if (UseParallelGC) { -#ifndef SERIALGC +#if INCLUDE_ALL_GCS Universe::_collectedHeap = new ParallelScavengeHeap(); -#else // SERIALGC +#else // INCLUDE_ALL_GCS fatal("UseParallelGC not supported in this VM."); -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS } else if (UseG1GC) { -#ifndef SERIALGC +#if INCLUDE_ALL_GCS G1CollectorPolicy* g1p = new G1CollectorPolicy(); G1CollectedHeap* g1h = new G1CollectedHeap(g1p); Universe::_collectedHeap = g1h; -#else // SERIALGC +#else // INCLUDE_ALL_GCS fatal("UseG1GC not supported in java kernel vm."); -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS } else { GenCollectorPolicy *gc_policy; @@ -761,15 +780,15 @@ if (UseSerialGC) { gc_policy = new MarkSweepPolicy(); } else if (UseConcMarkSweepGC) { -#ifndef SERIALGC +#if INCLUDE_ALL_GCS if (UseAdaptiveSizePolicy) { gc_policy = new ASConcurrentMarkSweepPolicy(); } else { gc_policy = new ConcurrentMarkSweepPolicy(); } -#else // SERIALGC +#else // INCLUDE_ALL_GCS fatal("UseConcMarkSweepGC not supported in this VM."); -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS } else { // default old generation gc_policy = new MarkSweepPolicy(); } @@ -796,7 +815,9 @@ tty->print("heap address: " PTR_FORMAT ", size: " SIZE_FORMAT " MB", Universe::heap()->base(), Universe::heap()->reserved_region().byte_size()/M); } - if ((uint64_t)Universe::heap()->reserved_region().end() > OopEncodingHeapMax) { + if (((uint64_t)Universe::heap()->reserved_region().end() > OopEncodingHeapMax) || + (UseCompressedKlassPointers && + ((uint64_t)Universe::heap()->base() + Universe::class_metaspace_size() > KlassEncodingMetaspaceMax))) { // Can't reserve heap below 32Gb. // keep the Universe::narrow_oop_base() set in Universe::reserve_heap() Universe::set_narrow_oop_shift(LogMinObjAlignmentInBytes); @@ -862,8 +883,8 @@ // be compressed the same as instances. // Need to round class space size up because it's below the heap and // the actual alignment depends on its size. - size_t metaspace_size = align_size_up(ClassMetaspaceSize, alignment); - size_t total_reserved = align_size_up(heap_size + metaspace_size, alignment); + Universe::set_class_metaspace_size(align_size_up(ClassMetaspaceSize, alignment)); + size_t total_reserved = align_size_up(heap_size + Universe::class_metaspace_size(), alignment); char* addr = Universe::preferred_heap_base(total_reserved, Universe::UnscaledNarrowOop); ReservedHeapSpace total_rs(total_reserved, alignment, UseLargePages, addr); @@ -904,8 +925,8 @@ // compressed oops is greater than the one used for compressed klass // ptrs, a metadata space on top of the heap could become // unreachable. - ReservedSpace class_rs = total_rs.first_part(metaspace_size); - ReservedSpace heap_rs = total_rs.last_part(metaspace_size, alignment); + ReservedSpace class_rs = total_rs.first_part(Universe::class_metaspace_size()); + ReservedSpace heap_rs = total_rs.last_part(Universe::class_metaspace_size(), alignment); Metaspace::initialize_class_space(class_rs); if (UseCompressedOops) { diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/memory/universe.hpp --- a/src/share/vm/memory/universe.hpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/memory/universe.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -211,6 +211,9 @@ static struct NarrowPtrStruct _narrow_klass; static address _narrow_ptrs_base; + // Aligned size of the metaspace. + static size_t _class_metaspace_size; + // array of dummy objects used with +FullGCAlot debug_only(static objArrayOop _fullgc_alot_dummy_array;) // index of next entry to clear @@ -278,6 +281,13 @@ static bool reserve_metaspace_helper(bool with_base = false); static ReservedHeapSpace reserve_heap_metaspace(size_t heap_size, size_t alignment, bool& contiguous); + static size_t class_metaspace_size() { + return _class_metaspace_size; + } + static void set_class_metaspace_size(size_t metaspace_size) { + _class_metaspace_size = metaspace_size; + } + // Debugging static int _verify_count; // number of verifies done // True during call to verify(). Should only be set/cleared in verify(). diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/oops/annotations.cpp --- a/src/share/vm/oops/annotations.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/oops/annotations.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,6 +24,7 @@ #include "precompiled.hpp" #include "classfile/classLoaderData.hpp" +#include "memory/heapInspection.hpp" #include "memory/metadataFactory.hpp" #include "memory/oopFactory.hpp" #include "oops/annotations.hpp" @@ -35,16 +36,8 @@ return new (loader_data, size(), true, THREAD) Annotations(); } -Annotations* Annotations::allocate(ClassLoaderData* loader_data, - Array* fa, - Array* ma, - Array* mpa, - Array* mda, TRAPS) { - return new (loader_data, size(), true, THREAD) Annotations(fa, ma, mpa, mda); -} - // helper -static void free_contents(ClassLoaderData* loader_data, Array* p) { +void Annotations::free_contents(ClassLoaderData* loader_data, Array* p) { if (p != NULL) { for (int i = 0; i < p->length(); i++) { MetadataFactory::free_array(loader_data, p->at(i)); @@ -58,44 +51,16 @@ MetadataFactory::free_array(loader_data, class_annotations()); } free_contents(loader_data, fields_annotations()); - free_contents(loader_data, methods_annotations()); - free_contents(loader_data, methods_parameter_annotations()); - free_contents(loader_data, methods_default_annotations()); - // Recursively deallocate optional Annotations linked through this one - MetadataFactory::free_metadata(loader_data, type_annotations()); + if (class_type_annotations() != NULL) { + MetadataFactory::free_array(loader_data, class_type_annotations()); + } + free_contents(loader_data, fields_type_annotations()); } -// Set the annotation at 'idnum' to 'anno'. -// We don't want to create or extend the array if 'anno' is NULL, since that is the -// default value. However, if the array exists and is long enough, we must set NULL values. -void Annotations::set_methods_annotations_of(instanceKlassHandle ik, - int idnum, AnnotationArray* anno, - Array** md_p, - TRAPS) { - Array* md = *md_p; - if (md != NULL && md->length() > idnum) { - md->at_put(idnum, anno); - } else if (anno != NULL) { - // create the array - int length = MAX2(idnum+1, (int)ik->idnum_allocated_count()); - md = MetadataFactory::new_array(ik->class_loader_data(), length, CHECK); - if (*md_p != NULL) { - // copy the existing entries - for (int index = 0; index < (*md_p)->length(); index++) { - md->at_put(index, (*md_p)->at(index)); - } - } - set_annotations(md, md_p); - md->at_put(idnum, anno); - } // if no array and idnum isn't included there is nothing to do -} - -// Keep created annotations in a global growable array (should be hashtable) -// need to add, search, delete when class is unloaded. -// Does it need a lock? yes. This sucks. - // Copy annotations to JVM call or reflection to the java heap. +// The alternative to creating this array and adding to Java heap pressure +// is to have a hashtable of the already created typeArrayOops typeArrayOop Annotations::make_java_array(AnnotationArray* annotations, TRAPS) { if (annotations != NULL) { int length = annotations->length(); @@ -114,14 +79,44 @@ st->print("Anotations(" INTPTR_FORMAT ")", this); } +#if INCLUDE_SERVICES +// Size Statistics + +julong Annotations::count_bytes(Array* p) { + julong bytes = 0; + if (p != NULL) { + for (int i = 0; i < p->length(); i++) { + bytes += KlassSizeStats::count_array(p->at(i)); + } + bytes += KlassSizeStats::count_array(p); + } + return bytes; +} + +void Annotations::collect_statistics(KlassSizeStats *sz) const { + sz->_annotations_bytes = sz->count(this); + sz->_class_annotations_bytes = sz->count(class_annotations()); + sz->_class_type_annotations_bytes = sz->count(class_type_annotations()); + sz->_fields_annotations_bytes = count_bytes(fields_annotations()); + sz->_fields_type_annotations_bytes = count_bytes(fields_type_annotations()); + + sz->_annotations_bytes += + sz->_class_annotations_bytes + + sz->_class_type_annotations_bytes + + sz->_fields_annotations_bytes + + sz->_fields_type_annotations_bytes; + + sz->_ro_bytes += sz->_annotations_bytes; +} +#endif // INCLUDE_SERVICES + #define BULLET " - " #ifndef PRODUCT void Annotations::print_on(outputStream* st) const { st->print(BULLET"class_annotations "); class_annotations()->print_value_on(st); st->print(BULLET"fields_annotations "); fields_annotations()->print_value_on(st); - st->print(BULLET"methods_annotations "); methods_annotations()->print_value_on(st); - st->print(BULLET"methods_parameter_annotations"); methods_parameter_annotations()->print_value_on(st); - st->print(BULLET"methods_default_annotations "); methods_default_annotations()->print_value_on(st); + st->print(BULLET"class_type_annotations "); class_type_annotations()->print_value_on(st); + st->print(BULLET"fields_type_annotations "); fields_type_annotations()->print_value_on(st); } #endif // PRODUCT diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/oops/annotations.hpp --- a/src/share/vm/oops/annotations.hpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/oops/annotations.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,6 +34,7 @@ class ClassLoaderData; class outputStream; +class KlassSizeStats; typedef Array AnnotationArray; @@ -48,101 +49,46 @@ // Annotation objects (byte arrays) for fields, or null if no annotations. // Indices correspond to entries (not indices) in fields array. Array* _fields_annotations; - // Annotation objects (byte arrays) for methods, or null if no annotations. - // Index is the idnum, which is initially the same as the methods array index. - Array* _methods_annotations; - // Annotation objects (byte arrays) for methods' parameters, or null if no - // such annotations. - // Index is the idnum, which is initially the same as the methods array index. - Array* _methods_parameter_annotations; - // Annotation objects (byte arrays) for methods' default values, or null if no - // such annotations. - // Index is the idnum, which is initially the same as the methods array index. - Array* _methods_default_annotations; // Type annotations for this class, or null if none. - Annotations* _type_annotations; - - // Constructor where some some values are known to not be null - Annotations(Array* fa, Array* ma, - Array* mpa, Array* mda) : - _class_annotations(NULL), - _fields_annotations(fa), - _methods_annotations(ma), - _methods_parameter_annotations(mpa), - _methods_default_annotations(mda), - _type_annotations(NULL) {} + AnnotationArray* _class_type_annotations; + Array* _fields_type_annotations; public: // Allocate instance of this class static Annotations* allocate(ClassLoaderData* loader_data, TRAPS); - static Annotations* allocate(ClassLoaderData* loader_data, - Array* fa, - Array* ma, - Array* mpa, - Array* mda, TRAPS); + + static void free_contents(ClassLoaderData* loader_data, Array* p); void deallocate_contents(ClassLoaderData* loader_data); DEBUG_ONLY(bool on_stack() { return false; }) // for template + + // Sizing (in words) static int size() { return sizeof(Annotations) / wordSize; } +#if INCLUDE_SERVICES + void collect_statistics(KlassSizeStats *sz) const; +#endif // Constructor to initialize to null Annotations() : _class_annotations(NULL), _fields_annotations(NULL), - _methods_annotations(NULL), - _methods_parameter_annotations(NULL), - _methods_default_annotations(NULL), - _type_annotations(NULL) {} + _class_type_annotations(NULL), + _fields_type_annotations(NULL) {} AnnotationArray* class_annotations() const { return _class_annotations; } Array* fields_annotations() const { return _fields_annotations; } - Array* methods_annotations() const { return _methods_annotations; } - Array* methods_parameter_annotations() const { return _methods_parameter_annotations; } - Array* methods_default_annotations() const { return _methods_default_annotations; } - Annotations* type_annotations() const { return _type_annotations; } + AnnotationArray* class_type_annotations() const { return _class_type_annotations; } + Array* fields_type_annotations() const { return _fields_type_annotations; } void set_class_annotations(AnnotationArray* md) { _class_annotations = md; } void set_fields_annotations(Array* md) { _fields_annotations = md; } - void set_methods_annotations(Array* md) { _methods_annotations = md; } - void set_methods_parameter_annotations(Array* md) { _methods_parameter_annotations = md; } - void set_methods_default_annotations(Array* md) { _methods_default_annotations = md; } - void set_type_annotations(Annotations* annos) { _type_annotations = annos; } - - // Redefine classes support - AnnotationArray* get_method_annotations_of(int idnum) - { return get_method_annotations_from(idnum, _methods_annotations); } - - AnnotationArray* get_method_parameter_annotations_of(int idnum) - { return get_method_annotations_from(idnum, _methods_parameter_annotations); } - AnnotationArray* get_method_default_annotations_of(int idnum) - { return get_method_annotations_from(idnum, _methods_default_annotations); } - - - void set_method_annotations_of(instanceKlassHandle ik, - int idnum, AnnotationArray* anno, TRAPS) { - set_methods_annotations_of(ik, idnum, anno, &_methods_annotations, THREAD); - } - - void set_method_parameter_annotations_of(instanceKlassHandle ik, - int idnum, AnnotationArray* anno, TRAPS) { - set_methods_annotations_of(ik, idnum, anno, &_methods_parameter_annotations, THREAD); - } - - void set_method_default_annotations_of(instanceKlassHandle ik, - int idnum, AnnotationArray* anno, TRAPS) { - set_methods_annotations_of(ik, idnum, anno, &_methods_default_annotations, THREAD); - } + void set_class_type_annotations(AnnotationArray* cta) { _class_type_annotations = cta; } + void set_fields_type_annotations(Array* fta) { _fields_type_annotations = fta; } // Turn metadata annotations into a Java heap object (oop) static typeArrayOop make_java_array(AnnotationArray* annotations, TRAPS); - inline AnnotationArray* get_method_annotations_from(int idnum, Array* annos); - void set_annotations(Array* md, Array** md_p) { *md_p = md; } - bool is_klass() const { return false; } private: - void set_methods_annotations_of(instanceKlassHandle ik, - int idnum, AnnotationArray* anno, - Array** md_p, TRAPS); - + static julong count_bytes(Array* p); public: const char* internal_name() const { return "{constant pool}"; } #ifndef PRODUCT @@ -150,13 +96,4 @@ #endif void print_value_on(outputStream* st) const; }; - - -// For method with idnum get the method's Annotations -inline AnnotationArray* Annotations::get_method_annotations_from(int idnum, Array* annos) { - if (annos == NULL || annos->length() <= idnum) { - return NULL; - } - return annos->at(idnum); -} #endif // SHARE_VM_OOPS_ANNOTATIONS_HPP diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/oops/arrayKlass.hpp --- a/src/share/vm/oops/arrayKlass.hpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/oops/arrayKlass.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -106,6 +106,14 @@ static int header_size() { return sizeof(ArrayKlass)/HeapWordSize; } static int static_size(int header_size); +#if INCLUDE_SERVICES + virtual void collect_statistics(KlassSizeStats *sz) const { + Klass::collect_statistics(sz); + // Do nothing for now, but remember to modify if you add new + // stuff to ArrayKlass. + } +#endif + // Java vtable klassVtable* vtable() const; // return new klassVtable int vtable_length() const { return _vtable_len; } diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/oops/constMethod.cpp --- a/src/share/vm/oops/constMethod.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/oops/constMethod.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ #include "precompiled.hpp" #include "interpreter/interpreter.hpp" #include "memory/gcLocker.hpp" +#include "memory/heapInspection.hpp" #include "memory/metadataFactory.hpp" #include "oops/constMethod.hpp" #include "oops/method.hpp" @@ -35,51 +36,26 @@ ConstMethod* ConstMethod::allocate(ClassLoaderData* loader_data, int byte_code_size, - int compressed_line_number_size, - int localvariable_table_length, - int exception_table_length, - int checked_exceptions_length, - int method_parameters_length, - u2 generic_signature_index, + InlineTableSizes* sizes, MethodType method_type, TRAPS) { - int size = ConstMethod::size(byte_code_size, - compressed_line_number_size, - localvariable_table_length, - exception_table_length, - checked_exceptions_length, - method_parameters_length, - generic_signature_index); + int size = ConstMethod::size(byte_code_size, sizes); return new (loader_data, size, true, THREAD) ConstMethod( - byte_code_size, compressed_line_number_size, localvariable_table_length, - exception_table_length, checked_exceptions_length, - method_parameters_length, generic_signature_index, - method_type, size); + byte_code_size, sizes, method_type, size); } ConstMethod::ConstMethod(int byte_code_size, - int compressed_line_number_size, - int localvariable_table_length, - int exception_table_length, - int checked_exceptions_length, - int method_parameters_length, - u2 generic_signature_index, + InlineTableSizes* sizes, MethodType method_type, int size) { No_Safepoint_Verifier no_safepoint; - set_interpreter_kind(Interpreter::invalid); init_fingerprint(); set_constants(NULL); set_stackmap_data(NULL); set_code_size(byte_code_size); set_constMethod_size(size); - set_inlined_tables_length(generic_signature_index, - checked_exceptions_length, - compressed_line_number_size, - localvariable_table_length, - exception_table_length, - method_parameters_length); + set_inlined_tables_length(sizes); set_method_type(method_type); assert(this->size() == size, "wrong size for object"); } @@ -87,47 +63,70 @@ // Deallocate metadata fields associated with ConstMethod* void ConstMethod::deallocate_contents(ClassLoaderData* loader_data) { - set_interpreter_kind(Interpreter::invalid); if (stackmap_data() != NULL) { MetadataFactory::free_array(loader_data, stackmap_data()); } set_stackmap_data(NULL); + + // deallocate annotation arrays + if (has_method_annotations()) + MetadataFactory::free_array(loader_data, method_annotations()); + if (has_parameter_annotations()) + MetadataFactory::free_array(loader_data, parameter_annotations()); + if (has_type_annotations()) + MetadataFactory::free_array(loader_data, type_annotations()); + if (has_default_annotations()) + MetadataFactory::free_array(loader_data, default_annotations()); } // How big must this constMethodObject be? int ConstMethod::size(int code_size, - int compressed_line_number_size, - int local_variable_table_length, - int exception_table_length, - int checked_exceptions_length, - int method_parameters_length, - u2 generic_signature_index) { + InlineTableSizes* sizes) { int extra_bytes = code_size; - if (compressed_line_number_size > 0) { - extra_bytes += compressed_line_number_size; + if (sizes->compressed_linenumber_size() > 0) { + extra_bytes += sizes->compressed_linenumber_size(); } - if (checked_exceptions_length > 0) { + if (sizes->checked_exceptions_length() > 0) { extra_bytes += sizeof(u2); - extra_bytes += checked_exceptions_length * sizeof(CheckedExceptionElement); + extra_bytes += sizes->checked_exceptions_length() * sizeof(CheckedExceptionElement); } - if (local_variable_table_length > 0) { + if (sizes->localvariable_table_length() > 0) { extra_bytes += sizeof(u2); extra_bytes += - local_variable_table_length * sizeof(LocalVariableTableElement); + sizes->localvariable_table_length() * sizeof(LocalVariableTableElement); } - if (exception_table_length > 0) { + if (sizes->exception_table_length() > 0) { extra_bytes += sizeof(u2); - extra_bytes += exception_table_length * sizeof(ExceptionTableElement); + extra_bytes += sizes->exception_table_length() * sizeof(ExceptionTableElement); } - if (generic_signature_index != 0) { + if (sizes->generic_signature_index() != 0) { extra_bytes += sizeof(u2); } - if (method_parameters_length > 0) { + if (sizes->method_parameters_length() > 0) { extra_bytes += sizeof(u2); - extra_bytes += method_parameters_length * sizeof(MethodParametersElement); + extra_bytes += sizes->method_parameters_length() * sizeof(MethodParametersElement); + } + + // Align sizes up to a word. + extra_bytes = align_size_up(extra_bytes, BytesPerWord); + + // One pointer per annotation array + if (sizes->method_annotations_length() > 0) { + extra_bytes += sizeof(AnnotationArray*); } + if (sizes->parameter_annotations_length() > 0) { + extra_bytes += sizeof(AnnotationArray*); + } + if (sizes->type_annotations_length() > 0) { + extra_bytes += sizeof(AnnotationArray*); + } + if (sizes->default_annotations_length() > 0) { + extra_bytes += sizeof(AnnotationArray*); + } + int extra_words = align_size_up(extra_bytes, BytesPerWord) / BytesPerWord; + assert(extra_words == extra_bytes/BytesPerWord, "should already be aligned"); return align_object_size(header_size() + extra_words); } @@ -144,12 +143,28 @@ return code_end(); } +// Last short in ConstMethod* before annotations +u2* ConstMethod::last_u2_element() const { + int offset = 0; + if (has_method_annotations()) offset++; + if (has_parameter_annotations()) offset++; + if (has_type_annotations()) offset++; + if (has_default_annotations()) offset++; + return (u2*)((AnnotationArray**)constMethod_end() - offset) - 1; +} + u2* ConstMethod::generic_signature_index_addr() const { // Located at the end of the constMethod. assert(has_generic_signature(), "called only if generic signature exists"); return last_u2_element(); } +u2* ConstMethod::method_parameters_length_addr() const { + assert(has_method_parameters(), "called only if table is present"); + return has_generic_signature() ? (last_u2_element() - 1) : + last_u2_element(); +} + u2* ConstMethod::checked_exceptions_length_addr() const { // Located immediately before the generic signature index. assert(has_checked_exceptions(), "called only if table is present"); @@ -163,12 +178,6 @@ } } -u2* ConstMethod::method_parameters_length_addr() const { - assert(has_method_parameters(), "called only if table is present"); - return has_generic_signature() ? (last_u2_element() - 1) : - last_u2_element(); -} - u2* ConstMethod::exception_table_length_addr() const { assert(has_exception_handler(), "called only if table is present"); if (has_checked_exceptions()) { @@ -180,9 +189,9 @@ return (u2*)method_parameters_start() - 1; } else { // Else, the exception table is at the end of the constMethod. - return has_generic_signature() ? (last_u2_element() - 1) : - last_u2_element(); - } + return has_generic_signature() ? (last_u2_element() - 1) : + last_u2_element(); + } } } @@ -203,32 +212,38 @@ // Else, the exception table is at the end of the constMethod. return has_generic_signature() ? (last_u2_element() - 1) : last_u2_element(); + } } } - } } // Update the flags to indicate the presence of these optional fields. -void ConstMethod::set_inlined_tables_length(u2 generic_signature_index, - int checked_exceptions_len, - int compressed_line_number_size, - int localvariable_table_len, - int exception_table_len, - int method_parameters_len) { - assert(_flags == 0, "Error"); - if (compressed_line_number_size > 0) +void ConstMethod::set_inlined_tables_length(InlineTableSizes* sizes) { + _flags = 0; + if (sizes->compressed_linenumber_size() > 0) _flags |= _has_linenumber_table; - if (generic_signature_index != 0) + if (sizes->generic_signature_index() != 0) _flags |= _has_generic_signature; - if (method_parameters_len > 0) + if (sizes->method_parameters_length() > 0) _flags |= _has_method_parameters; - if (checked_exceptions_len > 0) + if (sizes->checked_exceptions_length() > 0) _flags |= _has_checked_exceptions; - if (exception_table_len > 0) + if (sizes->exception_table_length() > 0) _flags |= _has_exception_table; - if (localvariable_table_len > 0) + if (sizes->localvariable_table_length() > 0) _flags |= _has_localvariable_table; + // annotations, they are all pointer sized embedded objects so don't have + // a length embedded also. + if (sizes->method_annotations_length() > 0) + _flags |= _has_method_annotations; + if (sizes->parameter_annotations_length() > 0) + _flags |= _has_parameter_annotations; + if (sizes->type_annotations_length() > 0) + _flags |= _has_type_annotations; + if (sizes->default_annotations_length() > 0) + _flags |= _has_default_annotations; + // This code is extremely brittle and should possibly be revised. // The *_length_addr functions walk backwards through the // constMethod data, using each of the length indexes ahead of them, @@ -241,17 +256,17 @@ // Also, the servicability agent needs to be informed anytime // anything is added here. It might be advisable to have some sort // of indication of this inline. - if (generic_signature_index != 0) - *(generic_signature_index_addr()) = generic_signature_index; + if (sizes->generic_signature_index() != 0) + *(generic_signature_index_addr()) = sizes->generic_signature_index(); // New data should probably go here. - if (method_parameters_len > 0) - *(method_parameters_length_addr()) = method_parameters_len; - if (checked_exceptions_len > 0) - *(checked_exceptions_length_addr()) = checked_exceptions_len; - if (exception_table_len > 0) - *(exception_table_length_addr()) = exception_table_len; - if (localvariable_table_len > 0) - *(localvariable_table_length_addr()) = localvariable_table_len; + if (sizes->method_parameters_length() > 0) + *(method_parameters_length_addr()) = sizes->method_parameters_length(); + if (sizes->checked_exceptions_length() > 0) + *(checked_exceptions_length_addr()) = sizes->checked_exceptions_length(); + if (sizes->exception_table_length() > 0) + *(exception_table_length_addr()) = sizes->exception_table_length(); + if (sizes->localvariable_table_length() > 0) + *(localvariable_table_length_addr()) = sizes->localvariable_table_length(); } int ConstMethod::method_parameters_length() const { @@ -306,6 +321,34 @@ return (ExceptionTableElement*)addr; } +AnnotationArray** ConstMethod::method_annotations_addr() const { + assert(has_method_annotations(), "should only be called if method annotations are present"); + return (AnnotationArray**)constMethod_end() - 1; +} + +AnnotationArray** ConstMethod::parameter_annotations_addr() const { + assert(has_parameter_annotations(), "should only be called if method parameter annotations are present"); + int offset = 1; + if (has_method_annotations()) offset++; + return (AnnotationArray**)constMethod_end() - offset; +} + +AnnotationArray** ConstMethod::type_annotations_addr() const { + assert(has_type_annotations(), "should only be called if method type annotations are present"); + int offset = 1; + if (has_method_annotations()) offset++; + if (has_parameter_annotations()) offset++; + return (AnnotationArray**)constMethod_end() - offset; +} + +AnnotationArray** ConstMethod::default_annotations_addr() const { + assert(has_default_annotations(), "should only be called if method default annotations are present"); + int offset = 1; + if (has_method_annotations()) offset++; + if (has_parameter_annotations()) offset++; + if (has_type_annotations()) offset++; + return (AnnotationArray**)constMethod_end() - offset; +} // Printing @@ -330,6 +373,35 @@ method()->print_value_on(st); } +#if INCLUDE_SERVICES +// Size Statistics +void ConstMethod::collect_statistics(KlassSizeStats *sz) const { + int n1, n2, n3; + sz->_const_method_bytes += (n1 = sz->count(this)); + sz->_bytecode_bytes += (n2 = code_size()); + sz->_stackmap_bytes += (n3 = sz->count_array(stackmap_data())); + + // Count method annotations + int a1 = 0, a2 = 0, a3 = 0, a4 = 0; + if (has_method_annotations()) { + sz->_methods_annotations_bytes += (a1 = sz->count_array(method_annotations())); + } + if (has_parameter_annotations()) { + sz->_methods_parameter_annotations_bytes += (a2 = sz->count_array(parameter_annotations())); + } + if (has_type_annotations()) { + sz->_methods_type_annotations_bytes += (a3 = sz->count_array(type_annotations())); + } + if (has_default_annotations()) { + sz->_methods_default_annotations_bytes += (a4 = sz->count_array(default_annotations())); + } + + int size_annotations = a1 + a2 + a3 + a4; + + sz->_method_all_bytes += n1 + n3 + size_annotations; // note: n2 is part of n3 + sz->_ro_bytes += n1 + n3 + size_annotations; +} +#endif // INCLUDE_SERVICES // Verification @@ -339,10 +411,9 @@ // Verification can occur during oop construction before the method or // other fields have been initialized. - guarantee(is_metadata(), err_msg("Should be metadata " PTR_FORMAT, this)); guarantee(method()->is_method(), "should be method"); - address m_end = (address)((oop*) this + size()); + address m_end = (address)((intptr_t) this + size()); address compressed_table_start = code_end(); guarantee(compressed_table_start <= m_end, "invalid method layout"); address compressed_table_end = compressed_table_start; diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/oops/constMethod.hpp --- a/src/share/vm/oops/constMethod.hpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/oops/constMethod.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -86,19 +86,22 @@ // | generic signature index (u2) | // | (indexed from start of constMethodOop) | // |------------------------------------------------------| +// | annotations arrays - method, parameter, type, default| +// | pointer to Array if annotation is present | +// |------------------------------------------------------| // // IMPORTANT: If anything gets added here, there need to be changes to // ensure that ServicabilityAgent doesn't get broken as a result! -// Utitily class decribing elements in checked exceptions table inlined in Method*. +// Utility class describing elements in checked exceptions table inlined in Method*. class CheckedExceptionElement VALUE_OBJ_CLASS_SPEC { public: u2 class_cp_index; }; -// Utitily class decribing elements in local variable table inlined in Method*. +// Utility class describing elements in local variable table inlined in Method*. class LocalVariableTableElement VALUE_OBJ_CLASS_SPEC { public: u2 start_bci; @@ -109,7 +112,7 @@ u2 slot; }; -// Utitily class describing elements in exception table +// Utility class describing elements in exception table class ExceptionTableElement VALUE_OBJ_CLASS_SPEC { public: u2 start_pc; @@ -122,14 +125,55 @@ class MethodParametersElement VALUE_OBJ_CLASS_SPEC { public: u2 name_cp_index; - // This has to happen, otherwise it will cause SIGBUS from a - // misaligned u4 on some architectures (ie SPARC) - // because MethodParametersElements are only aligned mod 2 - // within the ConstMethod container u2 flags_hi; - u2 flags_hi; - u2 flags_lo; + u2 flags; }; +class KlassSizeStats; + +// Class to collect the sizes of ConstMethod inline tables +#define INLINE_TABLES_DO(do_element) \ + do_element(localvariable_table_length) \ + do_element(compressed_linenumber_size) \ + do_element(exception_table_length) \ + do_element(checked_exceptions_length) \ + do_element(method_parameters_length) \ + do_element(generic_signature_index) \ + do_element(method_annotations_length) \ + do_element(parameter_annotations_length) \ + do_element(type_annotations_length) \ + do_element(default_annotations_length) + +#define INLINE_TABLE_DECLARE(sym) int _##sym; +#define INLINE_TABLE_PARAM(sym) int sym, +#define INLINE_TABLE_INIT(sym) _##sym(sym), +#define INLINE_TABLE_NULL(sym) _##sym(0), +#define INLINE_TABLE_ACCESSOR(sym) int sym() const { return _##sym; } + +class InlineTableSizes : StackObj { + // declarations + INLINE_TABLES_DO(INLINE_TABLE_DECLARE) + int _end; + public: + InlineTableSizes( + INLINE_TABLES_DO(INLINE_TABLE_PARAM) + int end) : + INLINE_TABLES_DO(INLINE_TABLE_INIT) + _end(end) {} + + // Default constructor for no inlined tables + InlineTableSizes() : + INLINE_TABLES_DO(INLINE_TABLE_NULL) + _end(0) {} + + // Accessors + INLINE_TABLES_DO(INLINE_TABLE_ACCESSOR) +}; +#undef INLINE_TABLE_ACCESSOR +#undef INLINE_TABLE_NULL +#undef INLINE_TABLE_INIT +#undef INLINE_TABLE_PARAM +#undef INLINE_TABLE_DECLARE + class ConstMethod : public MetaspaceObj { friend class VMStructs; @@ -139,13 +183,17 @@ private: enum { - _has_linenumber_table = 1, - _has_checked_exceptions = 2, - _has_localvariable_table = 4, - _has_exception_table = 8, - _has_generic_signature = 16, - _has_method_parameters = 32, - _is_overpass = 64 + _has_linenumber_table = 0x0001, + _has_checked_exceptions = 0x0002, + _has_localvariable_table = 0x0004, + _has_exception_table = 0x0008, + _has_generic_signature = 0x0010, + _has_method_parameters = 0x0020, + _is_overpass = 0x0040, + _has_method_annotations = 0x0080, + _has_parameter_annotations = 0x0100, + _has_type_annotations = 0x0200, + _has_default_annotations = 0x0400 }; // Bit vector of signature @@ -162,8 +210,7 @@ Array* _stackmap_data; int _constMethod_size; - jbyte _interpreter_kind; - jbyte _flags; + u2 _flags; // Size of Java bytecodes allocated immediately after Method*. u2 _code_size; @@ -178,36 +225,21 @@ // Constructor ConstMethod(int byte_code_size, - int compressed_line_number_size, - int localvariable_table_length, - int exception_table_length, - int checked_exceptions_length, - int method_parameters_length, - u2 generic_signature_index, + InlineTableSizes* sizes, MethodType is_overpass, int size); public: static ConstMethod* allocate(ClassLoaderData* loader_data, int byte_code_size, - int compressed_line_number_size, - int localvariable_table_length, - int exception_table_length, - int checked_exceptions_length, - int method_parameters_length, - u2 generic_signature_index, + InlineTableSizes* sizes, MethodType mt, TRAPS); bool is_constMethod() const { return true; } // Inlined tables - void set_inlined_tables_length(u2 generic_signature_index, - int checked_exceptions_len, - int compressed_line_number_size, - int localvariable_table_len, - int exception_table_len, - int method_parameters_length); + void set_inlined_tables_length(InlineTableSizes* sizes); bool has_generic_signature() const { return (_flags & _has_generic_signature) != 0; } @@ -239,10 +271,6 @@ } } - - void set_interpreter_kind(int kind) { _interpreter_kind = kind; } - int interpreter_kind(void) const { return _interpreter_kind; } - // constant pool ConstantPool* constants() const { return _constants; } void set_constants(ConstantPool* c) { _constants = c; } @@ -311,15 +339,13 @@ } // Size needed - static int size(int code_size, int compressed_line_number_size, - int local_variable_table_length, - int exception_table_length, - int checked_exceptions_length, - int method_parameters_length, - u2 generic_signature_index); + static int size(int code_size, InlineTableSizes* sizes); int size() const { return _constMethod_size;} void set_constMethod_size(int size) { _constMethod_size = size; } +#if INCLUDE_SERVICES + void collect_statistics(KlassSizeStats *sz) const; +#endif // code size int code_size() const { return _code_size; } @@ -355,6 +381,65 @@ int method_parameters_length() const; MethodParametersElement* method_parameters_start() const; + // method annotations + bool has_method_annotations() const + { return (_flags & _has_method_annotations) != 0; } + + bool has_parameter_annotations() const + { return (_flags & _has_parameter_annotations) != 0; } + + bool has_type_annotations() const + { return (_flags & _has_type_annotations) != 0; } + + bool has_default_annotations() const + { return (_flags & _has_default_annotations) != 0; } + + + AnnotationArray** method_annotations_addr() const; + AnnotationArray* method_annotations() const { + return has_method_annotations() ? *(method_annotations_addr()) : NULL; + } + void set_method_annotations(AnnotationArray* anno) { + *(method_annotations_addr()) = anno; + } + + AnnotationArray** parameter_annotations_addr() const; + AnnotationArray* parameter_annotations() const { + return has_parameter_annotations() ? *(parameter_annotations_addr()) : NULL; + } + void set_parameter_annotations(AnnotationArray* anno) { + *(parameter_annotations_addr()) = anno; + } + + AnnotationArray** type_annotations_addr() const; + AnnotationArray* type_annotations() const { + return has_type_annotations() ? *(type_annotations_addr()) : NULL; + } + void set_type_annotations(AnnotationArray* anno) { + *(type_annotations_addr()) = anno; + } + + AnnotationArray** default_annotations_addr() const; + AnnotationArray* default_annotations() const { + return has_default_annotations() ? *(default_annotations_addr()) : NULL; + } + void set_default_annotations(AnnotationArray* anno) { + *(default_annotations_addr()) = anno; + } + + int method_annotations_length() const { + return has_method_annotations() ? method_annotations()->length() : 0; + } + int parameter_annotations_length() const { + return has_parameter_annotations() ? parameter_annotations()->length() : 0; + } + int type_annotations_length() const { + return has_type_annotations() ? type_annotations()->length() : 0; + } + int default_annotations_length() const { + return has_default_annotations() ? default_annotations()->length() : 0; + } + // byte codes void set_code(address code) { if (code_size() > 0) { @@ -410,11 +495,10 @@ // First byte after ConstMethod* address constMethod_end() const - { return (address)((oop*)this + _constMethod_size); } + { return (address)((intptr_t*)this + _constMethod_size); } // Last short in ConstMethod* - u2* last_u2_element() const - { return (u2*)constMethod_end() - 1; } + u2* last_u2_element() const; public: // Printing diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/oops/constantPool.cpp --- a/src/share/vm/oops/constantPool.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/oops/constantPool.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -25,16 +25,17 @@ #include "precompiled.hpp" #include "classfile/classLoaderData.hpp" #include "classfile/javaClasses.hpp" +#include "classfile/metadataOnStackMark.hpp" #include "classfile/symbolTable.hpp" #include "classfile/systemDictionary.hpp" #include "classfile/vmSymbols.hpp" #include "interpreter/linkResolver.hpp" +#include "memory/heapInspection.hpp" #include "memory/metadataFactory.hpp" #include "memory/oopFactory.hpp" #include "oops/constantPool.hpp" #include "oops/instanceKlass.hpp" #include "oops/objArrayKlass.hpp" -#include "prims/jvmtiRedefineClasses.hpp" #include "runtime/fieldType.hpp" #include "runtime/init.hpp" #include "runtime/javaCalls.hpp" @@ -65,11 +66,10 @@ set_operands(NULL); set_pool_holder(NULL); set_flags(0); + // only set to non-zero if constant pool is merged by RedefineClasses set_version(0); set_lock(new Monitor(Monitor::nonleaf + 2, "A constant pool lock")); - // all fields are initialized; needed for GC - set_on_stack(false); // initialize tag array int length = tags->length(); @@ -100,18 +100,6 @@ set_lock(NULL); } -void ConstantPool::set_flag_at(FlagBit fb) { - const int MAX_STATE_CHANGES = 2; - for (int i = MAX_STATE_CHANGES + 10; i > 0; i--) { - int oflags = _flags; - int nflags = oflags | (1 << (int)fb); - if (Atomic::cmpxchg(nflags, &_flags, oflags) == oflags) - return; - } - assert(false, "failed to cmpxchg flags"); - _flags |= (1 << (int)fb); // better than nothing -} - objArrayOop ConstantPool::resolved_references() const { return (objArrayOop)JNIHandles::resolve(_resolved_references); } @@ -707,10 +695,6 @@ result_oop = string_at_impl(this_oop, index, cache_index, CHECK_NULL); break; - case JVM_CONSTANT_Object: - result_oop = this_oop->object_at(index); - break; - case JVM_CONSTANT_MethodHandleInError: case JVM_CONSTANT_MethodTypeInError: { @@ -1111,32 +1095,9 @@ } // end compare_entry_to() -// Copy this constant pool's entries at start_i to end_i (inclusive) -// to the constant pool to_cp's entries starting at to_i. A total of -// (end_i - start_i) + 1 entries are copied. -void ConstantPool::copy_cp_to_impl(constantPoolHandle from_cp, int start_i, int end_i, - constantPoolHandle to_cp, int to_i, TRAPS) { - - int dest_i = to_i; // leave original alone for debug purposes - - for (int src_i = start_i; src_i <= end_i; /* see loop bottom */ ) { - copy_entry_to(from_cp, src_i, to_cp, dest_i, CHECK); - - switch (from_cp->tag_at(src_i).value()) { - case JVM_CONSTANT_Double: - case JVM_CONSTANT_Long: - // double and long take two constant pool entries - src_i += 2; - dest_i += 2; - break; - - default: - // all others take one constant pool entry - src_i++; - dest_i++; - break; - } - } +void ConstantPool::copy_operands(constantPoolHandle from_cp, + constantPoolHandle to_cp, + TRAPS) { int from_oplen = operand_array_length(from_cp->operands()); int old_oplen = operand_array_length(to_cp->operands()); @@ -1164,7 +1125,7 @@ (len = old_off) * sizeof(u2)); fillp += len; // first part of src - Copy::conjoint_memory_atomic(to_cp->operands()->adr_at(0), + Copy::conjoint_memory_atomic(from_cp->operands()->adr_at(0), new_operands->adr_at(fillp), (len = from_off) * sizeof(u2)); fillp += len; @@ -1174,7 +1135,7 @@ (len = old_len - old_off) * sizeof(u2)); fillp += len; // second part of src - Copy::conjoint_memory_atomic(to_cp->operands()->adr_at(from_off), + Copy::conjoint_memory_atomic(from_cp->operands()->adr_at(from_off), new_operands->adr_at(fillp), (len = from_len - from_off) * sizeof(u2)); fillp += len; @@ -1192,8 +1153,39 @@ to_cp->set_operands(new_operands); } } +} // end copy_operands() -} // end copy_cp_to() + +// Copy this constant pool's entries at start_i to end_i (inclusive) +// to the constant pool to_cp's entries starting at to_i. A total of +// (end_i - start_i) + 1 entries are copied. +void ConstantPool::copy_cp_to_impl(constantPoolHandle from_cp, int start_i, int end_i, + constantPoolHandle to_cp, int to_i, TRAPS) { + + + int dest_i = to_i; // leave original alone for debug purposes + + for (int src_i = start_i; src_i <= end_i; /* see loop bottom */ ) { + copy_entry_to(from_cp, src_i, to_cp, dest_i, CHECK); + + switch (from_cp->tag_at(src_i).value()) { + case JVM_CONSTANT_Double: + case JVM_CONSTANT_Long: + // double and long take two constant pool entries + src_i += 2; + dest_i += 2; + break; + + default: + // all others take one constant pool entry + src_i++; + dest_i++; + break; + } + } + copy_operands(from_cp, to_cp, CHECK); + +} // end copy_cp_to_impl() // Copy this constant pool's entry at from_i to the constant pool @@ -1755,7 +1747,11 @@ void ConstantPool::set_on_stack(const bool value) { - _on_stack = value; + if (value) { + _flags |= _on_stack; + } else { + _flags &= ~_on_stack; + } if (value) MetadataOnStackMark::record(this); } @@ -1824,9 +1820,8 @@ st->print_cr(internal_name()); if (flags() != 0) { st->print(" - flags: 0x%x", flags()); - if (has_pseudo_string()) st->print(" has_pseudo_string"); - if (has_invokedynamic()) st->print(" has_invokedynamic"); if (has_preresolution()) st->print(" has_preresolution"); + if (on_stack()) st->print(" on_stack"); st->cr(); } if (pool_holder() != NULL) { @@ -1868,13 +1863,14 @@ st->print(" name_and_type_index=%d", uncached_name_and_type_ref_index_at(index)); break; case JVM_CONSTANT_String : - unresolved_string_at(index)->print_value_on(st); + if (is_pseudo_string_at(index)) { + oop anObj = pseudo_string_at(index); + anObj->print_value_on(st); + st->print(" {0x%lx}", (address)anObj); + } else { + unresolved_string_at(index)->print_value_on(st); + } break; - case JVM_CONSTANT_Object : { - oop anObj = object_at(index); - anObj->print_value_on(st); - st->print(" {0x%lx}", (address)anObj); - } break; case JVM_CONSTANT_Integer : st->print("%d", int_at(index)); break; @@ -1938,8 +1934,6 @@ void ConstantPool::print_value_on(outputStream* st) const { assert(is_constantPool(), "must be constantPool"); st->print("constant pool [%d]", length()); - if (has_pseudo_string()) st->print("/pseudo_string"); - if (has_invokedynamic()) st->print("/invokedynamic"); if (has_preresolution()) st->print("/preresolution"); if (operands() != NULL) st->print("/operands[%d]", operands()->length()); print_address_on(st); @@ -1954,6 +1948,20 @@ } } +#if INCLUDE_SERVICES +// Size Statistics +void ConstantPool::collect_statistics(KlassSizeStats *sz) const { + sz->_cp_all_bytes += (sz->_cp_bytes = sz->count(this)); + sz->_cp_all_bytes += (sz->_cp_tags_bytes = sz->count_array(tags())); + sz->_cp_all_bytes += (sz->_cp_cache_bytes = sz->count(cache())); + sz->_cp_all_bytes += (sz->_cp_operands_bytes = sz->count_array(operands())); + sz->_cp_all_bytes += (sz->_cp_refmap_bytes = sz->count_array(reference_map())); + + sz->_ro_bytes += sz->_cp_operands_bytes + sz->_cp_tags_bytes + + sz->_cp_refmap_bytes; + sz->_rw_bytes += sz->_cp_bytes + sz->_cp_cache_bytes; +} +#endif // INCLUDE_SERVICES // Verification diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/oops/constantPool.hpp --- a/src/share/vm/oops/constantPool.hpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/oops/constantPool.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -80,6 +80,7 @@ } }; +class KlassSizeStats; class ConstantPool : public Metadata { friend class VMStructs; friend class BytecodeInterpreter; // Directly extracts an oop in the pool for fast instanceof/checkcast @@ -95,11 +96,14 @@ jobject _resolved_references; Array* _reference_map; - int _flags; // a few header bits to describe contents for GC + enum { + _has_preresolution = 1, // Flags + _on_stack = 2 + }; + + int _flags; // old fashioned bit twiddling int _length; // number of elements in the array - bool _on_stack; // Redefined method still executing refers to this constant pool. - union { // set for CDS to restore resolved references int _resolved_reference_length; @@ -115,17 +119,8 @@ void set_operands(Array* operands) { _operands = operands; } - enum FlagBit { - FB_has_invokedynamic = 1, - FB_has_pseudo_string = 2, - FB_has_preresolution = 3 - }; - - int flags() const { return _flags; } - void set_flags(int f) { _flags = f; } - bool flag_at(FlagBit fb) const { return (_flags & (1 << (int)fb)) != 0; } - void set_flag_at(FlagBit fb); - // no clear_flag_at function; they only increase + int flags() const { return _flags; } + void set_flags(int f) { _flags = f; } private: intptr_t* base() const { return (intptr_t*) (((char*) this) + sizeof(ConstantPool)); } @@ -178,18 +173,14 @@ Array* tags() const { return _tags; } Array* operands() const { return _operands; } - bool has_pseudo_string() const { return flag_at(FB_has_pseudo_string); } - bool has_invokedynamic() const { return flag_at(FB_has_invokedynamic); } - bool has_preresolution() const { return flag_at(FB_has_preresolution); } - void set_pseudo_string() { set_flag_at(FB_has_pseudo_string); } - void set_invokedynamic() { set_flag_at(FB_has_invokedynamic); } - void set_preresolution() { set_flag_at(FB_has_preresolution); } + bool has_preresolution() const { return (_flags & _has_preresolution) != 0; } + void set_has_preresolution() { _flags |= _has_preresolution; } // Redefine classes support. If a method refering to this constant pool // is on the executing stack, or as a handle in vm code, this constant pool // can't be removed from the set of previous versions saved in the instance // class. - bool on_stack() const { return _on_stack; } + bool on_stack() const { return (_flags &_on_stack) != 0; } void set_on_stack(const bool value); // Klass holding pool @@ -325,14 +316,6 @@ resolved_references()->obj_at_put(obj_index, str); } - void set_object_tag_at(int which) { - release_tag_at_put(which, JVM_CONSTANT_Object); - } - - void object_at_put(int which, oop obj) { - resolved_references()->obj_at_put(cp_to_object_index(which), obj); - } - // For temporary use while constructing constant pool void string_index_at_put(int which, int string_index) { tag_at_put(which, JVM_CONSTANT_StringIndex); @@ -430,12 +413,6 @@ // Version that can be used before string oop array is created. oop uncached_string_at(int which, TRAPS); - oop object_at(int which) { - assert(tag_at(which).is_object(), "Corrupted constant pool"); - int obj_index = cp_to_object_index(which); - return resolved_references()->obj_at(obj_index); - } - // A "pseudo-string" is an non-string oop that has found is way into // a String entry. // Under EnableInvokeDynamic this can happen if the user patches a live @@ -455,10 +432,18 @@ return s; } + oop pseudo_string_at(int which) { + assert(tag_at(which).is_string(), "Corrupted constant pool"); + assert(unresolved_string_at(which) == NULL, "shouldn't have symbol"); + int obj_index = cp_to_object_index(which); + oop s = resolved_references()->obj_at(obj_index); + return s; + } + void pseudo_string_at_put(int which, int obj_index, oop x) { assert(EnableInvokeDynamic, ""); - set_pseudo_string(); // mark header assert(tag_at(which).is_string(), "Corrupted constant pool"); + unresolved_string_at_put(which, NULL); // indicates patched string string_at_put(which, obj_index, x); // this works just fine } @@ -686,9 +671,13 @@ return 0 <= index && index < length(); } + // Sizing (in words) static int header_size() { return sizeof(ConstantPool)/HeapWordSize; } static int size(int length) { return align_object_size(header_size() + length); } int size() const { return size(length()); } +#if INCLUDE_SERVICES + void collect_statistics(KlassSizeStats *sz) const; +#endif friend class ClassFileParser; friend class SystemDictionary; @@ -785,6 +774,7 @@ } static void copy_cp_to_impl(constantPoolHandle from_cp, int start_i, int end_i, constantPoolHandle to_cp, int to_i, TRAPS); static void copy_entry_to(constantPoolHandle from_cp, int from_i, constantPoolHandle to_cp, int to_i, TRAPS); + static void copy_operands(constantPoolHandle from_cp, constantPoolHandle to_cp, TRAPS); int find_matching_entry(int pattern_i, constantPoolHandle search_cp, TRAPS); int version() const { return _saved._version; } void set_version(int version) { _saved._version = version; } diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/oops/cpCache.cpp --- a/src/share/vm/oops/cpCache.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/oops/cpCache.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,9 +33,10 @@ #include "prims/jvmtiRedefineClassesTrace.hpp" #include "prims/methodHandles.hpp" #include "runtime/handles.inline.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS # include "gc_implementation/parallelScavenge/psPromotionManager.hpp" -#endif +#endif // INCLUDE_ALL_GCS // Implememtation of ConstantPoolCacheEntry @@ -401,8 +402,9 @@ } +#if INCLUDE_JVMTI // RedefineClasses() API support: -// If this constantPoolCacheEntry refers to old_method then update it +// If this ConstantPoolCacheEntry refers to old_method then update it // to refer to new_method. bool ConstantPoolCacheEntry::adjust_method_entry(Method* old_method, Method* new_method, bool * trace_name_printed) { @@ -460,16 +462,24 @@ return false; } -#ifndef PRODUCT -bool ConstantPoolCacheEntry::check_no_old_entries() { +// a constant pool cache entry should never contain old or obsolete methods +bool ConstantPoolCacheEntry::check_no_old_or_obsolete_entries() { if (is_vfinal()) { + // virtual and final so _f2 contains method ptr instead of vtable index Metadata* f2 = (Metadata*)_f2; - return (f2->is_valid() && f2->is_method() && !((Method*)f2)->is_old()); - } else { - return (_f1 == NULL || (_f1->is_valid() && _f1->is_method() && !((Method*)_f1)->is_old())); + // Return false if _f2 refers to an old or an obsolete method. + // _f2 == NULL || !_f2->is_method() are just as unexpected here. + return (f2 != NULL NOT_PRODUCT(&& f2->is_valid()) && f2->is_method() && + !((Method*)f2)->is_old() && !((Method*)f2)->is_obsolete()); + } else if (_f1 == NULL || + (NOT_PRODUCT(_f1->is_valid() &&) !_f1->is_method())) { + // _f1 == NULL || !_f1->is_method() are OK here + return true; } + // return false if _f1 refers to an old or an obsolete method + return (NOT_PRODUCT(_f1->is_valid() &&) _f1->is_method() && + !((Method*)_f1)->is_old() && !((Method*)_f1)->is_obsolete()); } -#endif bool ConstantPoolCacheEntry::is_interesting_method_entry(Klass* k) { if (!is_method_entry()) { @@ -502,13 +512,15 @@ // the method is in the interesting class so the entry is interesting return true; } +#endif // INCLUDE_JVMTI void ConstantPoolCacheEntry::print(outputStream* st, int index) const { // print separator if (index == 0) st->print_cr(" -------------"); // print entry st->print("%3d ("PTR_FORMAT") ", index, (intptr_t)this); - st->print_cr("[%02x|%02x|%5d]", bytecode_2(), bytecode_1(), constant_pool_index()); + st->print_cr("[%02x|%02x|%5d]", bytecode_2(), bytecode_1(), + constant_pool_index()); st->print_cr(" [ "PTR_FORMAT"]", (intptr_t)_f1); st->print_cr(" [ "PTR_FORMAT"]", (intptr_t)_f2); st->print_cr(" [ "PTR_FORMAT"]", (intptr_t)_flags); @@ -552,8 +564,9 @@ } } +#if INCLUDE_JVMTI // RedefineClasses() API support: -// If any entry of this constantPoolCache points to any of +// If any entry of this ConstantPoolCache points to any of // old_methods, replace it with the corresponding new_method. void ConstantPoolCache::adjust_method_entries(Method** old_methods, Method** new_methods, int methods_length, bool * trace_name_printed) { @@ -572,7 +585,7 @@ continue; } - // The constantPoolCache contains entries for several different + // The ConstantPoolCache contains entries for several different // things, but we only care about methods. In fact, we only care // about methods in the same class as the one that contains the // old_methods. At this point, we have an interesting entry. @@ -591,17 +604,25 @@ } } -#ifndef PRODUCT -bool ConstantPoolCache::check_no_old_entries() { +// the constant pool cache should never contain old or obsolete methods +bool ConstantPoolCache::check_no_old_or_obsolete_entries() { for (int i = 1; i < length(); i++) { if (entry_at(i)->is_interesting_method_entry(NULL) && - !entry_at(i)->check_no_old_entries()) { + !entry_at(i)->check_no_old_or_obsolete_entries()) { return false; } } return true; } -#endif // PRODUCT + +void ConstantPoolCache::dump_cache() { + for (int i = 1; i < length(); i++) { + if (entry_at(i)->is_interesting_method_entry(NULL)) { + entry_at(i)->print(tty, i); + } + } +} +#endif // INCLUDE_JVMTI // Printing diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/oops/cpCache.hpp --- a/src/share/vm/oops/cpCache.hpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/oops/cpCache.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -337,16 +337,18 @@ static ByteSize f2_offset() { return byte_offset_of(ConstantPoolCacheEntry, _f2); } static ByteSize flags_offset() { return byte_offset_of(ConstantPoolCacheEntry, _flags); } +#if INCLUDE_JVMTI // RedefineClasses() API support: - // If this constantPoolCacheEntry refers to old_method then update it + // If this ConstantPoolCacheEntry refers to old_method then update it // to refer to new_method. // trace_name_printed is set to true if the current call has // printed the klass name so that other routines in the adjust_* // group don't print the klass name. bool adjust_method_entry(Method* old_method, Method* new_method, bool * trace_name_printed); - NOT_PRODUCT(bool check_no_old_entries();) + bool check_no_old_or_obsolete_entries(); bool is_interesting_method_entry(Klass* k); +#endif // INCLUDE_JVMTI // Debugging & Printing void print (outputStream* st, int index) const; @@ -423,15 +425,18 @@ return (base_offset() + ConstantPoolCacheEntry::size_in_bytes() * index); } +#if INCLUDE_JVMTI // RedefineClasses() API support: - // If any entry of this constantPoolCache points to any of + // If any entry of this ConstantPoolCache points to any of // old_methods, replace it with the corresponding new_method. // trace_name_printed is set to true if the current call has // printed the klass name so that other routines in the adjust_* // group don't print the klass name. void adjust_method_entries(Method** old_methods, Method** new_methods, int methods_length, bool * trace_name_printed); - NOT_PRODUCT(bool check_no_old_entries();) + bool check_no_old_or_obsolete_entries(); + void dump_cache(); +#endif // INCLUDE_JVMTI // Deallocate - no fields to deallocate DEBUG_ONLY(bool on_stack() { return false; }) diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/oops/generateOopMap.cpp --- a/src/share/vm/oops/generateOopMap.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/oops/generateOopMap.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1853,7 +1853,6 @@ if (tag.is_klass() || tag.is_unresolved_klass() || tag.is_string() || - tag.is_object() || tag.is_method_handle() || tag.is_method_type()) { assert(bt == T_OBJECT, "Guard is incorrect"); diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/oops/instanceClassLoaderKlass.cpp --- a/src/share/vm/oops/instanceClassLoaderKlass.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/oops/instanceClassLoaderKlass.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -36,12 +36,13 @@ #include "oops/oop.inline.hpp" #include "oops/symbol.hpp" #include "runtime/handles.inline.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/parNew/parOopClosures.inline.hpp" #include "gc_implementation/parallelScavenge/psPromotionManager.inline.hpp" #include "gc_implementation/parallelScavenge/psScavenge.inline.hpp" #include "oops/oop.pcgc.inline.hpp" -#endif +#endif // INCLUDE_ALL_GCS #define if_do_metadata_checked(closure, nv_suffix) \ /* Make sure the non-virtual and the virtual versions match. */ \ @@ -73,7 +74,7 @@ return size; \ } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS #define InstanceClassLoaderKlass_OOP_OOP_ITERATE_BACKWARDS_DEFN(OopClosureType, nv_suffix) \ \ int InstanceClassLoaderKlass:: \ @@ -83,7 +84,7 @@ int size = InstanceKlass::oop_oop_iterate_backwards##nv_suffix(obj, closure); \ return size; \ } -#endif // !SERIALGC +#endif // INCLUDE_ALL_GCS #define InstanceClassLoaderKlass_OOP_OOP_ITERATE_DEFN_m(OopClosureType, nv_suffix) \ @@ -111,10 +112,10 @@ ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceClassLoaderKlass_OOP_OOP_ITERATE_DEFN) ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceClassLoaderKlass_OOP_OOP_ITERATE_DEFN) -#ifndef SERIALGC +#if INCLUDE_ALL_GCS ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceClassLoaderKlass_OOP_OOP_ITERATE_BACKWARDS_DEFN) ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceClassLoaderKlass_OOP_OOP_ITERATE_BACKWARDS_DEFN) -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceClassLoaderKlass_OOP_OOP_ITERATE_DEFN_m) ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceClassLoaderKlass_OOP_OOP_ITERATE_DEFN_m) @@ -129,7 +130,7 @@ } } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS void InstanceClassLoaderKlass::oop_follow_contents(ParCompactionManager* cm, oop obj) { InstanceKlass::oop_follow_contents(cm, obj); @@ -155,5 +156,5 @@ } return size_helper(); } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/oops/instanceClassLoaderKlass.hpp --- a/src/share/vm/oops/instanceClassLoaderKlass.hpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/oops/instanceClassLoaderKlass.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -26,6 +26,7 @@ #define SHARE_VM_OOPS_INSTANCECLASSLOADERKLASS_HPP #include "oops/instanceKlass.hpp" +#include "utilities/macros.hpp" // An InstanceClassLoaderKlass is a specialization of the InstanceKlass. It does // not add any field. It is added to walk the dependencies for the class loader @@ -61,13 +62,13 @@ ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceClassLoaderKlass_OOP_OOP_ITERATE_DECL) ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceClassLoaderKlass_OOP_OOP_ITERATE_DECL) -#ifndef SERIALGC +#if INCLUDE_ALL_GCS #define InstanceClassLoaderKlass_OOP_OOP_ITERATE_BACKWARDS_DECL(OopClosureType, nv_suffix) \ int oop_oop_iterate_backwards##nv_suffix(oop obj, OopClosureType* blk); ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceClassLoaderKlass_OOP_OOP_ITERATE_BACKWARDS_DECL) ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceClassLoaderKlass_OOP_OOP_ITERATE_BACKWARDS_DECL) -#endif // !SERIALGC +#endif // INCLUDE_ALL_GCS // Garbage collection void oop_follow_contents(oop obj); diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/oops/instanceKlass.cpp --- a/src/share/vm/oops/instanceKlass.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/oops/instanceKlass.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,6 +34,7 @@ #include "interpreter/rewriter.hpp" #include "jvmtifiles/jvmti.h" #include "memory/genOopClosures.inline.hpp" +#include "memory/heapInspection.hpp" #include "memory/metadataFactory.hpp" #include "memory/oopFactory.hpp" #include "oops/fieldStreams.hpp" @@ -55,7 +56,8 @@ #include "runtime/thread.inline.hpp" #include "services/threadService.hpp" #include "utilities/dtrace.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/concurrentMarkSweep/cmsOopClosures.inline.hpp" #include "gc_implementation/g1/g1CollectedHeap.inline.hpp" #include "gc_implementation/g1/g1OopClosures.inline.hpp" @@ -66,7 +68,7 @@ #include "gc_implementation/parallelScavenge/psPromotionManager.inline.hpp" #include "gc_implementation/parallelScavenge/psScavenge.inline.hpp" #include "oops/oop.pcgc.inline.hpp" -#endif +#endif // INCLUDE_ALL_GCS #ifdef COMPILER1 #include "c1/c1_Compiler.hpp" #endif @@ -164,20 +166,19 @@ volatile int InstanceKlass::_total_instanceKlass_count = 0; Klass* InstanceKlass::allocate_instance_klass(ClassLoaderData* loader_data, - int vtable_len, - int itable_len, - int static_field_size, - int nonstatic_oop_map_size, - ReferenceType rt, - AccessFlags access_flags, - Symbol* name, + int vtable_len, + int itable_len, + int static_field_size, + int nonstatic_oop_map_size, + ReferenceType rt, + AccessFlags access_flags, + Symbol* name, Klass* super_klass, - KlassHandle host_klass, - TRAPS) { + bool is_anonymous, + TRAPS) { int size = InstanceKlass::size(vtable_len, itable_len, nonstatic_oop_map_size, - access_flags.is_interface(), - !host_klass.is_null()); + access_flags.is_interface(), is_anonymous); // Allocation InstanceKlass* ik; @@ -185,25 +186,25 @@ if (name == vmSymbols::java_lang_Class()) { ik = new (loader_data, size, THREAD) InstanceMirrorKlass( vtable_len, itable_len, static_field_size, nonstatic_oop_map_size, rt, - access_flags, !host_klass.is_null()); + access_flags, is_anonymous); } else if (name == vmSymbols::java_lang_ClassLoader() || (SystemDictionary::ClassLoader_klass_loaded() && super_klass != NULL && super_klass->is_subtype_of(SystemDictionary::ClassLoader_klass()))) { ik = new (loader_data, size, THREAD) InstanceClassLoaderKlass( vtable_len, itable_len, static_field_size, nonstatic_oop_map_size, rt, - access_flags, !host_klass.is_null()); + access_flags, is_anonymous); } else { // normal class ik = new (loader_data, size, THREAD) InstanceKlass( vtable_len, itable_len, static_field_size, nonstatic_oop_map_size, rt, - access_flags, !host_klass.is_null()); + access_flags, is_anonymous); } } else { // reference klass ik = new (loader_data, size, THREAD) InstanceRefKlass( vtable_len, itable_len, static_field_size, nonstatic_oop_map_size, rt, - access_flags, !host_klass.is_null()); + access_flags, is_anonymous); } Atomic::inc(&_total_instanceKlass_count); @@ -2042,7 +2043,7 @@ assert_is_in_closed_subset) } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS void InstanceKlass::oop_follow_contents(ParCompactionManager* cm, oop obj) { assert(obj != NULL, "can't follow the content of NULL object"); @@ -2054,7 +2055,7 @@ PSParallelCompact::mark_and_push(cm, p), \ assert_is_in) } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS // closure's do_metadata() method dictates whether the given closure should be // applied to the klass ptr in the object header. @@ -2082,7 +2083,7 @@ return size_helper(); \ } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS #define InstanceKlass_OOP_OOP_ITERATE_BACKWARDS_DEFN(OopClosureType, nv_suffix) \ \ int InstanceKlass::oop_oop_iterate_backwards##nv_suffix(oop obj, \ @@ -2100,7 +2101,7 @@ assert_is_in_closed_subset) \ return size_helper(); \ } -#endif // !SERIALGC +#endif // INCLUDE_ALL_GCS #define InstanceKlass_OOP_OOP_ITERATE_DEFN_m(OopClosureType, nv_suffix) \ \ @@ -2124,10 +2125,10 @@ ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceKlass_OOP_OOP_ITERATE_DEFN) ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceKlass_OOP_OOP_ITERATE_DEFN_m) ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceKlass_OOP_OOP_ITERATE_DEFN_m) -#ifndef SERIALGC +#if INCLUDE_ALL_GCS ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceKlass_OOP_OOP_ITERATE_BACKWARDS_DEFN) ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceKlass_OOP_OOP_ITERATE_BACKWARDS_DEFN) -#endif // !SERIALGC +#endif // INCLUDE_ALL_GCS int InstanceKlass::oop_adjust_pointers(oop obj) { int size = size_helper(); @@ -2139,7 +2140,7 @@ return size; } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS void InstanceKlass::oop_push_contents(PSPromotionManager* pm, oop obj) { InstanceKlass_OOP_MAP_REVERSE_ITERATE( \ obj, \ @@ -2159,7 +2160,7 @@ return size; } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS void InstanceKlass::clean_implementors_list(BoolObjectClosure* is_alive) { assert(is_loader_alive(is_alive), "this klass should be live"); @@ -2791,7 +2792,10 @@ st->print("%s", source_debug_extension()); st->cr(); } - st->print(BULLET"annotations: "); annotations()->print_value_on(st); st->cr(); + st->print(BULLET"class annotations: "); class_annotations()->print_value_on(st); st->cr(); + st->print(BULLET"class type annotations: "); class_type_annotations()->print_value_on(st); st->cr(); + st->print(BULLET"field annotations: "); fields_annotations()->print_value_on(st); st->cr(); + st->print(BULLET"field type annotations: "); fields_type_annotations()->print_value_on(st); st->cr(); { ResourceMark rm; // PreviousVersionInfo objects returned via PreviousVersionWalker @@ -2960,6 +2964,52 @@ return external_name(); } +#if INCLUDE_SERVICES +// Size Statistics +void InstanceKlass::collect_statistics(KlassSizeStats *sz) const { + Klass::collect_statistics(sz); + + sz->_inst_size = HeapWordSize * size_helper(); + sz->_vtab_bytes = HeapWordSize * align_object_offset(vtable_length()); + sz->_itab_bytes = HeapWordSize * align_object_offset(itable_length()); + sz->_nonstatic_oopmap_bytes = HeapWordSize * + ((is_interface() || is_anonymous()) ? + align_object_offset(nonstatic_oop_map_size()) : + nonstatic_oop_map_size()); + + int n = 0; + n += (sz->_methods_array_bytes = sz->count_array(methods())); + n += (sz->_method_ordering_bytes = sz->count_array(method_ordering())); + n += (sz->_local_interfaces_bytes = sz->count_array(local_interfaces())); + n += (sz->_transitive_interfaces_bytes = sz->count_array(transitive_interfaces())); + n += (sz->_signers_bytes = sz->count_array(signers())); + n += (sz->_fields_bytes = sz->count_array(fields())); + n += (sz->_inner_classes_bytes = sz->count_array(inner_classes())); + sz->_ro_bytes += n; + + const ConstantPool* cp = constants(); + if (cp) { + cp->collect_statistics(sz); + } + + const Annotations* anno = annotations(); + if (anno) { + anno->collect_statistics(sz); + } + + const Array* methods_array = methods(); + if (methods()) { + for (int i = 0; i < methods_array->length(); i++) { + Method* method = methods_array->at(i); + if (method) { + sz->_method_count ++; + method->collect_statistics(sz); + } + } + } +} +#endif // INCLUDE_SERVICES + // Verification class VerifyFieldClosure: public OopClosure { diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/oops/instanceKlass.hpp --- a/src/share/vm/oops/instanceKlass.hpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/oops/instanceKlass.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,6 +36,7 @@ #include "runtime/os.hpp" #include "utilities/accessFlags.hpp" #include "utilities/bitMap.inline.hpp" +#include "utilities/macros.hpp" // An InstanceKlass is the VM level representation of a Java class. // It contains all information needed for at class at execution runtime. @@ -154,8 +155,8 @@ ReferenceType rt, AccessFlags access_flags, Symbol* name, - Klass* super_klass, - KlassHandle host_klass, + Klass* super_klass, + bool is_anonymous, TRAPS); InstanceKlass() { assert(DumpSharedSpaces || UseSharedSpaces, "only for CDS"); } @@ -256,6 +257,16 @@ // JVMTI fields can be moved to their own structure - see 6315920 unsigned char * _cached_class_file_bytes; // JVMTI: cached class file, before retransformable agent modified it in CFLH jint _cached_class_file_len; // JVMTI: length of above + + volatile u2 _idnum_allocated_count; // JNI/JVMTI: increments with the addition of methods, old ids don't change + + // Class states are defined as ClassState (see above). + // Place the _init_state here to utilize the unused 2-byte after + // _idnum_allocated_count. + u1 _init_state; // state of class + u1 _reference_type; // reference type + + JvmtiCachedClassFieldMap* _jvmti_cached_class_field_map; // JVMTI: used during heap iteration // Method array. @@ -281,15 +292,6 @@ // ... Array* _fields; - volatile u2 _idnum_allocated_count; // JNI/JVMTI: increments with the addition of methods, old ids don't change - - // Class states are defined as ClassState (see above). - // Place the _init_state here to utilize the unused 2-byte after - // _idnum_allocated_count. - u1 _init_state; // state of class - - u1 _reference_type; // reference type - // embedded Java vtable follows here // embedded Java itables follows here // embedded static fields follows here @@ -677,19 +679,19 @@ // annotations support Annotations* annotations() const { return _annotations; } void set_annotations(Annotations* anno) { _annotations = anno; } + AnnotationArray* class_annotations() const { - if (annotations() == NULL) return NULL; - return annotations()->class_annotations(); + return (_annotations != NULL) ? _annotations->class_annotations() : NULL; } Array* fields_annotations() const { - if (annotations() == NULL) return NULL; - return annotations()->fields_annotations(); + return (_annotations != NULL) ? _annotations->fields_annotations() : NULL; } - Annotations* type_annotations() const { - if (annotations() == NULL) return NULL; - return annotations()->type_annotations(); + AnnotationArray* class_type_annotations() const { + return (_annotations != NULL) ? _annotations->class_type_annotations() : NULL; } - + Array* fields_type_annotations() const { + return (_annotations != NULL) ? _annotations->fields_type_annotations() : NULL; + } // allocation instanceOop allocate_instance(TRAPS); @@ -808,6 +810,7 @@ // Sizing (in words) static int header_size() { return align_object_offset(sizeof(InstanceKlass)/HeapWordSize); } + static int size(int vtable_length, int itable_length, int nonstatic_oop_map_size, bool is_interface, bool is_anonymous) { @@ -826,6 +829,9 @@ is_interface(), is_anonymous()); } +#if INCLUDE_SERVICES + virtual void collect_statistics(KlassSizeStats *sz) const; +#endif static int vtable_start_offset() { return header_size(); } static int vtable_length_offset() { return offset_of(InstanceKlass, _vtable_len) / HeapWordSize; } @@ -842,10 +848,14 @@ return (OopMapBlock*)(start_of_itable() + align_object_offset(itable_length())); } + Klass** end_of_nonstatic_oop_maps() const { + return (Klass**)(start_of_nonstatic_oop_maps() + + nonstatic_oop_map_count()); + } + Klass** adr_implementor() const { if (is_interface()) { - return (Klass**)(start_of_nonstatic_oop_maps() + - nonstatic_oop_map_count()); + return (Klass**)end_of_nonstatic_oop_maps(); } else { return NULL; } @@ -857,8 +867,7 @@ if (adr_impl != NULL) { return adr_impl + 1; } else { - return (Klass**)(start_of_nonstatic_oop_maps() + - nonstatic_oop_map_count()); + return end_of_nonstatic_oop_maps(); } } else { return NULL; @@ -932,13 +941,13 @@ ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceKlass_OOP_OOP_ITERATE_DECL) ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceKlass_OOP_OOP_ITERATE_DECL) -#ifndef SERIALGC +#if INCLUDE_ALL_GCS #define InstanceKlass_OOP_OOP_ITERATE_BACKWARDS_DECL(OopClosureType, nv_suffix) \ int oop_oop_iterate_backwards##nv_suffix(oop obj, OopClosureType* blk); ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceKlass_OOP_OOP_ITERATE_BACKWARDS_DECL) ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceKlass_OOP_OOP_ITERATE_BACKWARDS_DECL) -#endif // !SERIALGC +#endif // INCLUDE_ALL_GCS u2 idnum_allocated_count() const { return _idnum_allocated_count; } private: diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/oops/instanceMirrorKlass.cpp --- a/src/share/vm/oops/instanceMirrorKlass.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/oops/instanceMirrorKlass.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -35,7 +35,8 @@ #include "oops/oop.inline.hpp" #include "oops/symbol.hpp" #include "runtime/handles.inline.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/concurrentMarkSweep/cmsOopClosures.inline.hpp" #include "gc_implementation/g1/g1CollectedHeap.inline.hpp" #include "gc_implementation/g1/g1OopClosures.inline.hpp" @@ -45,7 +46,7 @@ #include "gc_implementation/parallelScavenge/psPromotionManager.inline.hpp" #include "gc_implementation/parallelScavenge/psScavenge.inline.hpp" #include "oops/oop.pcgc.inline.hpp" -#endif +#endif // INCLUDE_ALL_GCS int InstanceMirrorKlass::_offset_of_static_fields = 0; @@ -168,7 +169,7 @@ assert_is_in_closed_subset) } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS void InstanceMirrorKlass::oop_follow_contents(ParCompactionManager* cm, oop obj) { InstanceKlass::oop_follow_contents(cm, obj); @@ -189,7 +190,7 @@ PSParallelCompact::mark_and_push(cm, p), \ assert_is_in) } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS int InstanceMirrorKlass::oop_adjust_pointers(oop obj) { int size = oop_size(obj); @@ -262,7 +263,7 @@ } \ } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS #define InstanceMirrorKlass_OOP_OOP_ITERATE_BACKWARDS_DEFN(OopClosureType, nv_suffix) \ \ int InstanceMirrorKlass:: \ @@ -278,7 +279,7 @@ InstanceMirrorKlass_SPECIALIZED_OOP_ITERATE_DEFN(oop, nv_suffix); \ } \ } -#endif // !SERIALGC +#endif // INCLUDE_ALL_GCS #define InstanceMirrorKlass_OOP_OOP_ITERATE_DEFN_m(OopClosureType, nv_suffix) \ @@ -310,14 +311,14 @@ ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceMirrorKlass_OOP_OOP_ITERATE_DEFN) ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceMirrorKlass_OOP_OOP_ITERATE_DEFN) -#ifndef SERIALGC +#if INCLUDE_ALL_GCS ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceMirrorKlass_OOP_OOP_ITERATE_BACKWARDS_DEFN) ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceMirrorKlass_OOP_OOP_ITERATE_BACKWARDS_DEFN) -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceMirrorKlass_OOP_OOP_ITERATE_DEFN_m) ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceMirrorKlass_OOP_OOP_ITERATE_DEFN_m) -#ifndef SERIALGC +#if INCLUDE_ALL_GCS void InstanceMirrorKlass::oop_push_contents(PSPromotionManager* pm, oop obj) { // Note that we don't have to follow the mirror -> klass pointer, since all // klasses that are dirty will be scavenged when we iterate over the @@ -353,7 +354,7 @@ assert_nothing) return size; } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS int InstanceMirrorKlass::instance_size(KlassHandle k) { if (k() != NULL && k->oop_is_instance()) { diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/oops/instanceMirrorKlass.hpp --- a/src/share/vm/oops/instanceMirrorKlass.hpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/oops/instanceMirrorKlass.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -28,6 +28,7 @@ #include "classfile/systemDictionary.hpp" #include "oops/instanceKlass.hpp" #include "runtime/handles.hpp" +#include "utilities/macros.hpp" // An InstanceMirrorKlass is a specialized InstanceKlass for // java.lang.Class instances. These instances are special because @@ -107,13 +108,13 @@ ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceMirrorKlass_OOP_OOP_ITERATE_DECL) ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceMirrorKlass_OOP_OOP_ITERATE_DECL) -#ifndef SERIALGC +#if INCLUDE_ALL_GCS #define InstanceMirrorKlass_OOP_OOP_ITERATE_BACKWARDS_DECL(OopClosureType, nv_suffix) \ int oop_oop_iterate_backwards##nv_suffix(oop obj, OopClosureType* blk); ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceMirrorKlass_OOP_OOP_ITERATE_BACKWARDS_DECL) ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceMirrorKlass_OOP_OOP_ITERATE_BACKWARDS_DECL) -#endif // !SERIALGC +#endif // INCLUDE_ALL_GCS }; #endif // SHARE_VM_OOPS_INSTANCEMIRRORKLASS_HPP diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/oops/instanceRefKlass.cpp --- a/src/share/vm/oops/instanceRefKlass.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/oops/instanceRefKlass.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -33,7 +33,8 @@ #include "oops/instanceRefKlass.hpp" #include "oops/oop.inline.hpp" #include "utilities/preserveException.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/g1/g1CollectedHeap.inline.hpp" #include "gc_implementation/g1/g1OopClosures.inline.hpp" #include "gc_implementation/g1/g1RemSet.inline.hpp" @@ -42,7 +43,7 @@ #include "gc_implementation/parallelScavenge/psPromotionManager.inline.hpp" #include "gc_implementation/parallelScavenge/psScavenge.inline.hpp" #include "oops/oop.pcgc.inline.hpp" -#endif +#endif // INCLUDE_ALL_GCS template void specialized_oop_follow_contents(InstanceRefKlass* ref, oop obj) { @@ -120,7 +121,7 @@ } } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS template void specialized_oop_follow_contents(InstanceRefKlass* ref, ParCompactionManager* cm, @@ -194,7 +195,7 @@ specialized_oop_follow_contents(this, cm, obj); } } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS #ifdef ASSERT template void trace_reference_gc(const char *s, oop obj, @@ -317,7 +318,7 @@ } \ } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS #define InstanceRefKlass_OOP_OOP_ITERATE_BACKWARDS_DEFN(OopClosureType, nv_suffix) \ \ int InstanceRefKlass:: \ @@ -333,7 +334,7 @@ InstanceRefKlass_SPECIALIZED_OOP_ITERATE(oop, nv_suffix, contains); \ } \ } -#endif // !SERIALGC +#endif // INCLUDE_ALL_GCS #define InstanceRefKlass_OOP_OOP_ITERATE_DEFN_m(OopClosureType, nv_suffix) \ @@ -354,14 +355,14 @@ ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceRefKlass_OOP_OOP_ITERATE_DEFN) ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceRefKlass_OOP_OOP_ITERATE_DEFN) -#ifndef SERIALGC +#if INCLUDE_ALL_GCS ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceRefKlass_OOP_OOP_ITERATE_BACKWARDS_DEFN) ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceRefKlass_OOP_OOP_ITERATE_BACKWARDS_DEFN) -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceRefKlass_OOP_OOP_ITERATE_DEFN_m) ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceRefKlass_OOP_OOP_ITERATE_DEFN_m) -#ifndef SERIALGC +#if INCLUDE_ALL_GCS template void specialized_oop_push_contents(InstanceRefKlass *ref, PSPromotionManager* pm, oop obj) { @@ -444,7 +445,7 @@ } return size_helper(); } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS void InstanceRefKlass::update_nonstatic_oop_maps(Klass* k) { // Clear the nonstatic oop-map entries corresponding to referent diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/oops/instanceRefKlass.hpp --- a/src/share/vm/oops/instanceRefKlass.hpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/oops/instanceRefKlass.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -26,6 +26,7 @@ #define SHARE_VM_OOPS_INSTANCEREFKLASS_HPP #include "oops/instanceKlass.hpp" +#include "utilities/macros.hpp" // An InstanceRefKlass is a specialized InstanceKlass for Java // classes that are subclasses of java/lang/ref/Reference. @@ -83,13 +84,13 @@ ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceRefKlass_OOP_OOP_ITERATE_DECL) ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceRefKlass_OOP_OOP_ITERATE_DECL) -#ifndef SERIALGC +#if INCLUDE_ALL_GCS #define InstanceRefKlass_OOP_OOP_ITERATE_BACKWARDS_DECL(OopClosureType, nv_suffix) \ int oop_oop_iterate_backwards##nv_suffix(oop obj, OopClosureType* blk); ALL_OOP_OOP_ITERATE_CLOSURES_1(InstanceRefKlass_OOP_OOP_ITERATE_BACKWARDS_DECL) ALL_OOP_OOP_ITERATE_CLOSURES_2(InstanceRefKlass_OOP_OOP_ITERATE_BACKWARDS_DECL) -#endif // !SERIALGC +#endif // INCLUDE_ALL_GCS static void release_and_notify_pending_list_lock(BasicLock *pending_list_basic_lock); static void acquire_pending_list_lock(BasicLock *pending_list_basic_lock); diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/oops/klass.cpp --- a/src/share/vm/oops/klass.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/oops/klass.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,6 +29,7 @@ #include "classfile/vmSymbols.hpp" #include "gc_implementation/shared/markSweep.inline.hpp" #include "gc_interface/collectedHeap.inline.hpp" +#include "memory/heapInspection.hpp" #include "memory/metadataFactory.hpp" #include "memory/oopFactory.hpp" #include "memory/resourceArea.hpp" @@ -37,11 +38,12 @@ #include "oops/oop.inline2.hpp" #include "runtime/atomic.hpp" #include "utilities/stack.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/parallelScavenge/psParallelCompact.hpp" #include "gc_implementation/parallelScavenge/psPromotionManager.hpp" #include "gc_implementation/parallelScavenge/psScavenge.hpp" -#endif +#endif // INCLUDE_ALL_GCS void Klass::set_name(Symbol* n) { _name = n; @@ -624,6 +626,17 @@ obj->print_address_on(st); } +#if INCLUDE_SERVICES +// Size Statistics +void Klass::collect_statistics(KlassSizeStats *sz) const { + sz->_klass_bytes = sz->count(this); + sz->_mirror_bytes = sz->count(java_mirror()); + sz->_secondary_supers_bytes = sz->count_array(secondary_supers()); + + sz->_ro_bytes += sz->_secondary_supers_bytes; + sz->_rw_bytes += sz->_klass_bytes + sz->_mirror_bytes; +} +#endif // INCLUDE_SERVICES // Verification diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/oops/klass.hpp --- a/src/share/vm/oops/klass.hpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/oops/klass.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,11 +35,12 @@ #include "runtime/orderAccess.hpp" #include "trace/traceMacros.hpp" #include "utilities/accessFlags.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/concurrentMarkSweep/cmsOopClosures.hpp" #include "gc_implementation/g1/g1OopClosures.hpp" #include "gc_implementation/parNew/parOopClosures.hpp" -#endif +#endif // INCLUDE_ALL_GCS // // A Klass provides: @@ -75,11 +76,11 @@ // [class_loader_data] // [modifier_flags] // [access_flags ] -// [verify_count ] - not in product -// [alloc_count ] // [last_biased_lock_bulk_revocation_time] (64 bits) // [prototype_header] // [biased_lock_revocation_count] +// [verify_count ] - not in product +// [alloc_count ] // [_modified_oops] // [_accumulated_modified_oops] // [trace_id] @@ -91,6 +92,7 @@ class ClassLoaderData; class klassVtable; class ParCompactionManager; +class KlassSizeStats; class Klass : public Metadata { friend class VMStructs; @@ -168,18 +170,18 @@ jint _modifier_flags; // Processed access flags, for use by Class.getModifiers. AccessFlags _access_flags; // Access flags. The class/interface distinction is stored here. + // Biased locking implementation and statistics + // (the 64-bit chunk goes first, to avoid some fragmentation) + jlong _last_biased_lock_bulk_revocation_time; + markOop _prototype_header; // Used when biased locking is both enabled and disabled for this type + jint _biased_lock_revocation_count; + #ifndef PRODUCT int _verify_count; // to avoid redundant verifies #endif juint _alloc_count; // allocation profiling support - // Biased locking implementation and statistics - // (the 64-bit chunk goes first, to avoid some fragmentation) - jlong _last_biased_lock_bulk_revocation_time; - markOop _prototype_header; // Used when biased locking is both enabled and disabled for this type - jint _biased_lock_revocation_count; - TRACE_DEFINE_KLASS_TRACE_ID; // Remembered sets support for the oops in the klasses. @@ -489,6 +491,9 @@ // Size of klass in word size. virtual int size() const = 0; +#if INCLUDE_SERVICES + virtual void collect_statistics(KlassSizeStats *sz) const; +#endif // Returns the Java name for a class (Resource allocated) // For arrays, this returns the name of the element with a leading '['. @@ -637,13 +642,13 @@ return oop_oop_iterate(obj, blk); } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS // In case we don't have a specialized backward scanner use forward // iteration. virtual int oop_oop_iterate_backwards_v(oop obj, ExtendedOopClosure* blk) { return oop_oop_iterate_v(obj, blk); } -#endif // !SERIALGC +#endif // INCLUDE_ALL_GCS // Iterates "blk" over all the oops in "obj" (of type "this") within "mr". // (I don't see why the _m should be required, but without it the Solaris @@ -675,7 +680,7 @@ SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_1(Klass_OOP_OOP_ITERATE_DECL) SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_2(Klass_OOP_OOP_ITERATE_DECL) -#ifndef SERIALGC +#if INCLUDE_ALL_GCS #define Klass_OOP_OOP_ITERATE_BACKWARDS_DECL(OopClosureType, nv_suffix) \ virtual int oop_oop_iterate_backwards##nv_suffix(oop obj, \ OopClosureType* blk) { \ @@ -685,7 +690,7 @@ SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_1(Klass_OOP_OOP_ITERATE_BACKWARDS_DECL) SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_2(Klass_OOP_OOP_ITERATE_BACKWARDS_DECL) -#endif // !SERIALGC +#endif // INCLUDE_ALL_GCS virtual void array_klasses_do(void f(Klass* k)) {} virtual void with_array_klasses_do(void f(Klass* k)); diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/oops/klassPS.hpp --- a/src/share/vm/oops/klassPS.hpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/oops/klassPS.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -27,7 +27,9 @@ // Expands to Parallel Scavenge and Parallel Old declarations -#ifndef SERIALGC +#include "utilities/macros.hpp" + +#if INCLUDE_ALL_GCS #define PARALLEL_GC_DECLS \ virtual void oop_push_contents(PSPromotionManager* pm, oop obj); \ /* Parallel Old GC support \ @@ -44,9 +46,9 @@ virtual void oop_push_contents(PSPromotionManager* pm, oop obj) = 0; \ virtual void oop_follow_contents(ParCompactionManager* cm, oop obj) = 0; \ virtual int oop_update_pointers(ParCompactionManager* cm, oop obj) = 0; -#else // SERIALGC +#else // INCLUDE_ALL_GCS #define PARALLEL_GC_DECLS #define PARALLEL_GC_DECLS_PV -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS #endif // SHARE_VM_OOPS_KLASSPS_HPP diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/oops/klassVtable.cpp --- a/src/share/vm/oops/klassVtable.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/oops/klassVtable.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -610,6 +610,7 @@ Copy::disjoint_words((HeapWord*)table(), (HeapWord*)start, _length * vtableEntry::size()); } +#if INCLUDE_JVMTI void klassVtable::adjust_method_entries(Method** old_methods, Method** new_methods, int methods_length, bool * trace_name_printed) { // search the vtable for uses of either obsolete or EMCP methods @@ -638,11 +639,39 @@ new_method->name()->as_C_string(), new_method->signature()->as_C_string())); } + // cannot 'break' here; see for-loop comment above. } } } } +// a vtable should never contain old or obsolete methods +bool klassVtable::check_no_old_or_obsolete_entries() { + for (int i = 0; i < length(); i++) { + Method* m = unchecked_method_at(i); + if (m != NULL && + (NOT_PRODUCT(!m->is_valid() ||) m->is_old() || m->is_obsolete())) { + return false; + } + } + return true; +} + +void klassVtable::dump_vtable() { + tty->print_cr("vtable dump --"); + for (int i = 0; i < length(); i++) { + Method* m = unchecked_method_at(i); + if (m != NULL) { + tty->print(" (%5d) ", i); + m->access_flags().print_on(tty); + tty->print(" -- "); + m->print_name(tty); + tty->cr(); + } + } +} +#endif // INCLUDE_JVMTI + // CDS/RedefineClasses support - clear vtables so they can be reinitialized void klassVtable::clear_vtable() { for (int i = 0; i < _length; i++) table()[i].clear(); @@ -805,6 +834,7 @@ } } +#if INCLUDE_JVMTI void klassItable::adjust_method_entries(Method** old_methods, Method** new_methods, int methods_length, bool * trace_name_printed) { // search the itable for uses of either obsolete or EMCP methods @@ -833,13 +863,44 @@ new_method->name()->as_C_string(), new_method->signature()->as_C_string())); } - // Cannot break because there might be another entry for this method + // cannot 'break' here; see for-loop comment above. } ime++; } } } +// an itable should never contain old or obsolete methods +bool klassItable::check_no_old_or_obsolete_entries() { + itableMethodEntry* ime = method_entry(0); + for (int i = 0; i < _size_method_table; i++) { + Method* m = ime->method(); + if (m != NULL && + (NOT_PRODUCT(!m->is_valid() ||) m->is_old() || m->is_obsolete())) { + return false; + } + ime++; + } + return true; +} + +void klassItable::dump_itable() { + itableMethodEntry* ime = method_entry(0); + tty->print_cr("itable dump --"); + for (int i = 0; i < _size_method_table; i++) { + Method* m = ime->method(); + if (m != NULL) { + tty->print(" (%5d) ", i); + m->access_flags().print_on(tty); + tty->print(" -- "); + m->print_name(tty); + tty->cr(); + } + ime++; + } +} +#endif // INCLUDE_JVMTI + // Setup class InterfaceVisiterClosure : public StackObj { @@ -1126,43 +1187,6 @@ tty->print_cr("%6d bytes total", total); } -bool klassVtable::check_no_old_entries() { - // Check that there really is no entry - for (int i = 0; i < length(); i++) { - Method* m = unchecked_method_at(i); - if (m != NULL) { - if (!m->is_valid() || m->is_old()) { - return false; - } - } - } - return true; -} - -void klassVtable::dump_vtable() { - tty->print_cr("vtable dump --"); - for (int i = 0; i < length(); i++) { - Method* m = unchecked_method_at(i); - if (m != NULL) { - tty->print(" (%5d) ", i); - m->access_flags().print_on(tty); - tty->print(" -- "); - m->print_name(tty); - tty->cr(); - } - } -} - -bool klassItable::check_no_old_entries() { - itableMethodEntry* ime = method_entry(0); - for(int i = 0; i < _size_method_table; i++) { - Method* m = ime->method(); - if (m != NULL && (!m->is_valid() || m->is_old())) return false; - ime++; - } - return true; -} - int klassItable::_total_classes; // Total no. of classes with itables long klassItable::_total_size; // Total no. of bytes used for itables diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/oops/klassVtable.hpp --- a/src/share/vm/oops/klassVtable.hpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/oops/klassVtable.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -90,6 +90,7 @@ Array* methods, AccessFlags class_flags, Handle classloader, Symbol* classname, Array* local_interfaces, TRAPS); +#if INCLUDE_JVMTI // RedefineClasses() API support: // If any entry of this vtable points to any of old_methods, // replace it with the corresponding new_method. @@ -98,17 +99,15 @@ // group don't print the klass name. void adjust_method_entries(Method** old_methods, Method** new_methods, int methods_length, bool * trace_name_printed); + bool check_no_old_or_obsolete_entries(); + void dump_vtable(); +#endif // INCLUDE_JVMTI // Debugging code void print() PRODUCT_RETURN; void verify(outputStream* st, bool force = false); static void print_statistics() PRODUCT_RETURN; -#ifndef PRODUCT - bool check_no_old_entries(); - void dump_vtable(); -#endif - protected: friend class vtableEntry; private: @@ -275,6 +274,7 @@ // Updates void initialize_with_method(Method* m); +#if INCLUDE_JVMTI // RedefineClasses() API support: // if any entry of this itable points to any of old_methods, // replace it with the corresponding new_method. @@ -283,6 +283,9 @@ // group don't print the klass name. void adjust_method_entries(Method** old_methods, Method** new_methods, int methods_length, bool * trace_name_printed); + bool check_no_old_or_obsolete_entries(); + void dump_itable(); +#endif // INCLUDE_JVMTI // Setup of itable static int compute_itable_size(Array* transitive_interfaces); @@ -307,11 +310,6 @@ NOT_PRODUCT(static long _total_size;) // Total no. of bytes used for itables static void update_stats(int size) PRODUCT_RETURN NOT_PRODUCT({ _total_classes++; _total_size += size; }) - - public: -#ifndef PRODUCT - bool check_no_old_entries(); -#endif }; #endif // SHARE_VM_OOPS_KLASSVTABLE_HPP diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/oops/method.cpp --- a/src/share/vm/oops/method.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/oops/method.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,7 @@ */ #include "precompiled.hpp" +#include "classfile/metadataOnStackMark.hpp" #include "classfile/systemDictionary.hpp" #include "code/debugInfoRec.hpp" #include "gc_interface/collectedHeap.inline.hpp" @@ -33,6 +34,7 @@ #include "interpreter/oopMapCache.hpp" #include "memory/gcLocker.hpp" #include "memory/generation.hpp" +#include "memory/heapInspection.hpp" #include "memory/metadataFactory.hpp" #include "memory/oopFactory.hpp" #include "oops/constMethod.hpp" @@ -41,7 +43,6 @@ #include "oops/oop.inline.hpp" #include "oops/symbol.hpp" #include "prims/jvmtiExport.hpp" -#include "prims/jvmtiRedefineClasses.hpp" #include "prims/methodHandles.hpp" #include "prims/nativeLookup.hpp" #include "runtime/arguments.hpp" @@ -63,24 +64,14 @@ Method* Method::allocate(ClassLoaderData* loader_data, int byte_code_size, AccessFlags access_flags, - int compressed_line_number_size, - int localvariable_table_length, - int exception_table_length, - int checked_exceptions_length, - int method_parameters_length, - u2 generic_signature_index, + InlineTableSizes* sizes, ConstMethod::MethodType method_type, TRAPS) { assert(!access_flags.is_native() || byte_code_size == 0, "native methods should not contain byte codes"); ConstMethod* cm = ConstMethod::allocate(loader_data, byte_code_size, - compressed_line_number_size, - localvariable_table_length, - exception_table_length, - checked_exceptions_length, - method_parameters_length, - generic_signature_index, + sizes, method_type, CHECK_NULL); @@ -324,14 +315,6 @@ } -void Method::set_interpreter_kind() { - int kind = Interpreter::method_kind(this); - assert(kind != Interpreter::invalid, - "interpreter entry must be valid"); - set_interpreter_kind(kind); -} - - // Attempt to return method oop to original state. Clear any pointers // (to objects outside the shared spaces). We won't be able to predict // where they should point in a new JVM. Further initialize some @@ -339,7 +322,6 @@ void Method::remove_unshareable_info() { unlink_method(); - set_interpreter_kind(); } @@ -707,7 +689,7 @@ } -void Method::print_made_not_compilable(int comp_level, bool is_osr, bool report) { +void Method::print_made_not_compilable(int comp_level, bool is_osr, bool report, const char* reason) { if (PrintCompilation && report) { ttyLocker ttyl; tty->print("made not %scompilable on ", is_osr ? "OSR " : ""); @@ -721,8 +703,12 @@ } this->print_short_name(tty); int size = this->code_size(); - if (size > 0) + if (size > 0) { tty->print(" (%d bytes)", size); + } + if (reason != NULL) { + tty->print(" %s", reason); + } tty->cr(); } if ((TraceDeoptimization || LogCompilation) && (xtty != NULL)) { @@ -730,6 +716,9 @@ ttyLocker ttyl; xtty->begin_elem("make_not_%scompilable thread='" UINTX_FORMAT "'", is_osr ? "osr_" : "", os::current_thread_id()); + if (reason != NULL) { + xtty->print(" reason=\'%s\'", reason); + } xtty->method(this); xtty->stamp(); xtty->end_elem(); @@ -751,8 +740,8 @@ } // call this when compiler finds that this method is not compilable -void Method::set_not_compilable(int comp_level, bool report) { - print_made_not_compilable(comp_level, /*is_osr*/ false, report); +void Method::set_not_compilable(int comp_level, bool report, const char* reason) { + print_made_not_compilable(comp_level, /*is_osr*/ false, report, reason); if (comp_level == CompLevel_all) { set_not_c1_compilable(); set_not_c2_compilable(); @@ -777,8 +766,8 @@ return false; } -void Method::set_not_osr_compilable(int comp_level, bool report) { - print_made_not_compilable(comp_level, /*is_osr*/ true, report); +void Method::set_not_osr_compilable(int comp_level, bool report, const char* reason) { + print_made_not_compilable(comp_level, /*is_osr*/ true, report, reason); if (comp_level == CompLevel_all) { set_not_c1_osr_compilable(); set_not_c2_osr_compilable(); @@ -1036,7 +1025,7 @@ cp->set_pool_holder(InstanceKlass::cast(holder())); cp->symbol_at_put(_imcp_invoke_name, name); cp->symbol_at_put(_imcp_invoke_signature, signature); - cp->set_preresolution(); + cp->set_has_preresolution(); // decide on access bits: public or not? int flags_bits = (JVM_ACC_NATIVE | JVM_ACC_SYNTHETIC | JVM_ACC_FINAL); @@ -1046,9 +1035,9 @@ methodHandle m; { + InlineTableSizes sizes; Method* m_oop = Method::allocate(loader_data, 0, - accessFlags_from(flags_bits), - 0, 0, 0, 0, 0, 0, + accessFlags_from(flags_bits), &sizes, ConstMethod::NORMAL, CHECK_(empty)); m = methodHandle(THREAD, m_oop); } @@ -1097,22 +1086,35 @@ assert(!m->is_native(), "cannot rewrite native methods"); // Allocate new Method* AccessFlags flags = m->access_flags(); - u2 generic_signature_index = m->generic_signature_index(); - int checked_exceptions_len = m->checked_exceptions_length(); - int localvariable_len = m->localvariable_table_length(); - int exception_table_len = m->exception_table_length(); - int method_parameters_len = m->method_parameters_length(); + + ConstMethod* cm = m->constMethod(); + int checked_exceptions_len = cm->checked_exceptions_length(); + int localvariable_len = cm->localvariable_table_length(); + int exception_table_len = cm->exception_table_length(); + int method_parameters_len = cm->method_parameters_length(); + int method_annotations_len = cm->method_annotations_length(); + int parameter_annotations_len = cm->parameter_annotations_length(); + int type_annotations_len = cm->type_annotations_length(); + int default_annotations_len = cm->default_annotations_length(); + + InlineTableSizes sizes( + localvariable_len, + new_compressed_linenumber_size, + exception_table_len, + checked_exceptions_len, + method_parameters_len, + cm->generic_signature_index(), + method_annotations_len, + parameter_annotations_len, + type_annotations_len, + default_annotations_len, + 0); ClassLoaderData* loader_data = m->method_holder()->class_loader_data(); Method* newm_oop = Method::allocate(loader_data, new_code_length, flags, - new_compressed_linenumber_size, - localvariable_len, - exception_table_len, - checked_exceptions_len, - method_parameters_len, - generic_signature_index, + &sizes, m->method_type(), CHECK_(methodHandle())); methodHandle newm (THREAD, newm_oop); @@ -1312,29 +1314,6 @@ MethodHandles::print_as_basic_type_signature_on(st, signature(), true); } -// This is only done during class loading, so it is OK to assume method_idnum matches the methods() array -static void reorder_based_on_method_index(Array* methods, - Array* annotations, - GrowableArray* temp_array) { - if (annotations == NULL) { - return; - } - - int length = methods->length(); - int i; - // Copy to temp array - temp_array->clear(); - for (i = 0; i < length; i++) { - temp_array->append(annotations->at(i)); - } - - // Copy back using old method indices - for (i = 0; i < length; i++) { - Method* m = methods->at(i); - annotations->at_put(i, temp_array->at(m->method_idnum())); - } -} - // Comparer for sorting an object array containing // Method*s. static int method_comparator(Method* a, Method* b) { @@ -1342,48 +1321,13 @@ } // This is only done during class loading, so it is OK to assume method_idnum matches the methods() array -void Method::sort_methods(Array* methods, - Array* methods_annotations, - Array* methods_parameter_annotations, - Array* methods_default_annotations, - Array* methods_type_annotations, - bool idempotent) { +void Method::sort_methods(Array* methods, bool idempotent) { int length = methods->length(); if (length > 1) { - bool do_annotations = false; - if (methods_annotations != NULL || - methods_parameter_annotations != NULL || - methods_default_annotations != NULL || - methods_type_annotations != NULL) { - do_annotations = true; - } - if (do_annotations) { - // Remember current method ordering so we can reorder annotations - for (int i = 0; i < length; i++) { - Method* m = methods->at(i); - m->set_method_idnum(i); - } - } { No_Safepoint_Verifier nsv; QuickSort::sort(methods->data(), length, method_comparator, idempotent); } - - // Sort annotations if necessary - assert(methods_annotations == NULL || methods_annotations->length() == methods->length(), ""); - assert(methods_parameter_annotations == NULL || methods_parameter_annotations->length() == methods->length(), ""); - assert(methods_default_annotations == NULL || methods_default_annotations->length() == methods->length(), ""); - assert(methods_type_annotations == NULL || methods_type_annotations->length() == methods->length(), ""); - if (do_annotations) { - ResourceMark rm; - // Allocate temporary storage - GrowableArray* temp_array = new GrowableArray(length); - reorder_based_on_method_index(methods, methods_annotations, temp_array); - reorder_based_on_method_index(methods, methods_parameter_annotations, temp_array); - reorder_based_on_method_index(methods, methods_default_annotations, temp_array); - reorder_based_on_method_index(methods, methods_type_annotations, temp_array); - } - // Reset method ordering for (int i = 0; i < length; i++) { Method* m = methods->at(i); @@ -1394,9 +1338,9 @@ //----------------------------------------------------------------------------------- -// Non-product code +// Non-product code unless JVM/TI needs it -#ifndef PRODUCT +#if !defined(PRODUCT) || INCLUDE_JVMTI class SignatureTypePrinter : public SignatureTypeNames { private: outputStream* _st; @@ -1431,8 +1375,13 @@ sig.print_parameters(); st->print(")"); } +#endif // !PRODUCT || INCLUDE_JVMTI +//----------------------------------------------------------------------------------- +// Non-product code + +#ifndef PRODUCT void Method::print_codes_on(outputStream* st) const { print_codes_on(0, code_size(), st); } @@ -1963,6 +1912,22 @@ if (WizardMode && code() != NULL) st->print(" ((nmethod*)%p)", code()); } +#if INCLUDE_SERVICES +// Size Statistics +void Method::collect_statistics(KlassSizeStats *sz) const { + int mysize = sz->count(this); + sz->_method_bytes += mysize; + sz->_method_all_bytes += mysize; + sz->_rw_bytes += mysize; + + if (constMethod()) { + constMethod()->collect_statistics(sz); + } + if (method_data()) { + method_data()->collect_statistics(sz); + } +} +#endif // INCLUDE_SERVICES // Verification diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/oops/method.hpp --- a/src/share/vm/oops/method.hpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/oops/method.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -101,6 +101,8 @@ class AdapterHandlerEntry; class MethodData; class ConstMethod; +class InlineTableSizes; +class KlassSizeStats; class Method : public Metadata { friend class VMStructs; @@ -131,8 +133,8 @@ int _graal_priority; #endif #ifdef TIERED + float _rate; // Events (invocation and backedge counter increments) per millisecond jlong _prev_time; // Previous time the rate was acquired - float _rate; // Events (invocation and backedge counter increments) per millisecond #endif #ifndef PRODUCT @@ -160,12 +162,7 @@ static Method* allocate(ClassLoaderData* loader_data, int byte_code_size, AccessFlags access_flags, - int compressed_line_number_size, - int localvariable_table_length, - int exception_table_length, - int checked_exceptions_length, - int method_parameters_length, - u2 generic_signature_index, + InlineTableSizes* sizes, ConstMethod::MethodType method_type, TRAPS); @@ -210,33 +207,17 @@ // annotations support AnnotationArray* annotations() const { - InstanceKlass* ik = method_holder(); - if (ik->annotations() == NULL) { - return NULL; - } - return ik->annotations()->get_method_annotations_of(method_idnum()); + return constMethod()->method_annotations(); } AnnotationArray* parameter_annotations() const { - InstanceKlass* ik = method_holder(); - if (ik->annotations() == NULL) { - return NULL; - } - return ik->annotations()->get_method_parameter_annotations_of(method_idnum()); + return constMethod()->parameter_annotations(); } AnnotationArray* annotation_default() const { - InstanceKlass* ik = method_holder(); - if (ik->annotations() == NULL) { - return NULL; - } - return ik->annotations()->get_method_default_annotations_of(method_idnum()); + return constMethod()->default_annotations(); } - AnnotationArray* type_annotations() const { - InstanceKlass* ik = method_holder(); - Annotations* type_annos = ik->type_annotations(); - if (type_annos == NULL) - return NULL; - return type_annos->get_method_annotations_of(method_idnum()); -} + AnnotationArray* type_annotations() const { + return constMethod()->type_annotations(); + } #ifdef CC_INTERP void set_result_index(BasicType type); @@ -450,13 +431,6 @@ address interpreter_entry() const { return _i2i_entry; } // Only used when first initialize so we can set _i2i_entry and _from_interpreted_entry void set_interpreter_entry(address entry) { _i2i_entry = entry; _from_interpreted_entry = entry; } - int interpreter_kind(void) { - return constMethod()->interpreter_kind(); - } - void set_interpreter_kind(); - void set_interpreter_kind(int kind) { - constMethod()->set_interpreter_kind(kind); - } // native function (used for native methods only) enum { @@ -494,6 +468,8 @@ void print_codes_on(int from, int to, outputStream* st) const PRODUCT_RETURN; // method parameters + bool has_method_parameters() const + { return constMethod()->has_method_parameters(); } int method_parameters_length() const { return constMethod()->method_parameters_length(); } MethodParametersElement* method_parameters_start() const @@ -605,6 +581,9 @@ static int header_size() { return sizeof(Method)/HeapWordSize; } static int size(bool is_native); int size() const { return method_size(); } +#if INCLUDE_SERVICES + void collect_statistics(KlassSizeStats *sz) const; +#endif // interpreter support static ByteSize const_offset() { return byte_offset_of(Method, _constMethod ); } @@ -776,18 +755,18 @@ // whether it is not compilable for another reason like having a // breakpoint set in it. bool is_not_compilable(int comp_level = CompLevel_any) const; - void set_not_compilable(int comp_level = CompLevel_all, bool report = true); + void set_not_compilable(int comp_level = CompLevel_all, bool report = true, const char* reason = NULL); void set_not_compilable_quietly(int comp_level = CompLevel_all) { set_not_compilable(comp_level, false); } bool is_not_osr_compilable(int comp_level = CompLevel_any) const; - void set_not_osr_compilable(int comp_level = CompLevel_all, bool report = true); + void set_not_osr_compilable(int comp_level = CompLevel_all, bool report = true, const char* reason = NULL); void set_not_osr_compilable_quietly(int comp_level = CompLevel_all) { set_not_osr_compilable(comp_level, false); } private: - void print_made_not_compilable(int comp_level, bool is_osr, bool report); + void print_made_not_compilable(int comp_level, bool is_osr, bool report, const char* reason); public: bool is_not_c1_compilable() const { return access_flags().is_not_c1_compilable(); } @@ -812,16 +791,15 @@ static bool has_unloaded_classes_in_signature(methodHandle m, TRAPS); // Printing - void print_short_name(outputStream* st = tty) /*PRODUCT_RETURN*/; // prints as klassname::methodname; Exposed so field engineers can debug VM + void print_short_name(outputStream* st = tty); // prints as klassname::methodname; Exposed so field engineers can debug VM +#if INCLUDE_JVMTI + void print_name(outputStream* st = tty); // prints as "virtual void foo(int)"; exposed for TraceRedefineClasses +#else void print_name(outputStream* st = tty) PRODUCT_RETURN; // prints as "virtual void foo(int)" +#endif // Helper routine used for method sorting - static void sort_methods(Array* methods, - Array* methods_annotations, - Array* methods_parameter_annotations, - Array* methods_default_annotations, - Array* methods_type_annotations, - bool idempotent = false); + static void sort_methods(Array* methods, bool idempotent = false); // Deallocation function for redefine classes or if an error occurs void deallocate_contents(ClassLoaderData* loader_data); diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/oops/methodData.cpp --- a/src/share/vm/oops/methodData.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/oops/methodData.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,6 +27,7 @@ #include "interpreter/bytecode.hpp" #include "interpreter/bytecodeStream.hpp" #include "interpreter/linkResolver.hpp" +#include "memory/heapInspection.hpp" #include "oops/methodData.hpp" #include "prims/jvmtiRedefineClasses.hpp" #include "runtime/compilationPolicy.hpp" @@ -890,6 +891,15 @@ } #endif +#if INCLUDE_SERVICES +// Size Statistics +void MethodData::collect_statistics(KlassSizeStats *sz) const { + int n = sz->count(this); + sz->_method_data_bytes += n; + sz->_method_all_bytes += n; + sz->_rw_bytes += n; +} +#endif // INCLUDE_SERVICES // Verification diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/oops/methodData.hpp --- a/src/share/vm/oops/methodData.hpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/oops/methodData.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,6 +32,7 @@ #include "runtime/orderAccess.hpp" class BytecodeStream; +class KlassSizeStats; // The MethodData object collects counts and other profile information // during zeroth-tier (interpretive) and first-tier execution. @@ -1301,6 +1302,9 @@ // My size int size_in_bytes() const { return _size; } int size() const { return align_object_size(align_size_up(_size, BytesPerWord)/BytesPerWord); } +#if INCLUDE_SERVICES + void collect_statistics(KlassSizeStats *sz) const; +#endif int creation_mileage() const { return _creation_mileage; } void set_creation_mileage(int x) { _creation_mileage = x; } @@ -1471,7 +1475,12 @@ uint decompile_count() const { return _nof_decompiles; } - void inc_decompile_count(); + void inc_decompile_count() { + _nof_decompiles += 1; + if (decompile_count() > (uint)PerMethodRecompilationCutoff) { + method()->set_not_compilable(CompLevel_full_optimization, true, "decompile_count > PerMethodRecompilationCutoff"); + } + } // Support for code generation static ByteSize data_offset() { diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/oops/objArrayKlass.cpp --- a/src/share/vm/oops/objArrayKlass.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/oops/objArrayKlass.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -43,7 +43,8 @@ #include "runtime/handles.inline.hpp" #include "runtime/mutexLocker.hpp" #include "utilities/copy.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/concurrentMarkSweep/cmsOopClosures.inline.hpp" #include "gc_implementation/g1/g1CollectedHeap.inline.hpp" #include "gc_implementation/g1/g1OopClosures.inline.hpp" @@ -54,7 +55,7 @@ #include "gc_implementation/parallelScavenge/psPromotionManager.inline.hpp" #include "gc_implementation/parallelScavenge/psScavenge.inline.hpp" #include "oops/oop.pcgc.inline.hpp" -#endif +#endif // INCLUDE_ALL_GCS ObjArrayKlass* ObjArrayKlass::allocate(ClassLoaderData* loader_data, int n, KlassHandle klass_handle, Symbol* name, TRAPS) { assert(ObjArrayKlass::header_size() <= InstanceKlass::header_size(), @@ -461,7 +462,7 @@ } } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS void ObjArrayKlass::oop_follow_contents(ParCompactionManager* cm, oop obj) { assert(obj->is_array(), "obj must be array"); @@ -472,7 +473,7 @@ objarray_follow_contents(cm, obj, 0); } } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS #define if_do_metadata_checked(closure, nv_suffix) \ /* Make sure the non-virtual and the virtual versions match. */ \ @@ -573,7 +574,7 @@ return size; } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS void ObjArrayKlass::oop_push_contents(PSPromotionManager* pm, oop obj) { assert(obj->is_objArray(), "obj must be obj array"); ObjArrayKlass_OOP_ITERATE( \ @@ -591,7 +592,7 @@ ObjArrayKlass_OOP_ITERATE(a, p, PSParallelCompact::adjust_pointer(p)) return size; } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS // JVM support diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/oops/objArrayKlass.hpp --- a/src/share/vm/oops/objArrayKlass.hpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/oops/objArrayKlass.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -28,6 +28,7 @@ #include "classfile/classLoaderData.hpp" #include "memory/specialized_oop_closures.hpp" #include "oops/arrayKlass.hpp" +#include "utilities/macros.hpp" // ObjArrayKlass is the klass for objArrays @@ -111,11 +112,11 @@ // Parallel Scavenge and Parallel Old PARALLEL_GC_DECLS -#ifndef SERIALGC +#if INCLUDE_ALL_GCS inline void oop_follow_contents(ParCompactionManager* cm, oop obj, int index); template inline void objarray_follow_contents(ParCompactionManager* cm, oop obj, int index); -#endif // !SERIALGC +#endif // INCLUDE_ALL_GCS // Iterators int oop_oop_iterate(oop obj, ExtendedOopClosure* blk) { diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/oops/objArrayKlass.inline.hpp --- a/src/share/vm/oops/objArrayKlass.inline.hpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/oops/objArrayKlass.inline.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -27,10 +27,11 @@ #include "gc_implementation/shared/markSweep.inline.hpp" #include "oops/objArrayKlass.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/parallelScavenge/psCompactionManager.inline.hpp" #include "gc_implementation/parallelScavenge/psParallelCompact.hpp" -#endif +#endif // INCLUDE_ALL_GCS void ObjArrayKlass::oop_follow_contents(oop obj, int index) { if (UseCompressedOops) { @@ -63,7 +64,7 @@ } } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS void ObjArrayKlass::oop_follow_contents(ParCompactionManager* cm, oop obj, int index) { if (UseCompressedOops) { @@ -96,6 +97,6 @@ cm->push_objarray(a, end_index); // Push the continuation. } } -#endif // #ifndef SERIALGC +#endif // INCLUDE_ALL_GCS #endif // SHARE_VM_OOPS_OBJARRAYKLASS_INLINE_HPP diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/oops/oop.hpp --- a/src/share/vm/oops/oop.hpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/oops/oop.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -29,6 +29,7 @@ #include "memory/memRegion.hpp" #include "memory/specialized_oop_closures.hpp" #include "oops/metadata.hpp" +#include "utilities/macros.hpp" #include "utilities/top.hpp" // oopDesc is the top baseclass for objects classes. The {name}Desc classes describe @@ -298,7 +299,7 @@ // reference field in "this". void follow_contents(void); -#ifndef SERIALGC +#if INCLUDE_ALL_GCS // Parallel Scavenge void push_contents(PSPromotionManager* pm); @@ -306,7 +307,7 @@ void update_contents(ParCompactionManager* cm); void follow_contents(ParCompactionManager* cm); -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS bool is_scavengable() const; @@ -316,13 +317,13 @@ void forward_to(oop p); bool cas_forward_to(oop p, markOop compare); -#ifndef SERIALGC +#if INCLUDE_ALL_GCS // Like "forward_to", but inserts the forwarding pointer atomically. // Exactly one thread succeeds in inserting the forwarding pointer, and // this call returns "NULL" for that thread; any other thread has the // value of the forwarding pointer returned and does not modify "this". oop forward_to_atomic(oop p); -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS oop forwardee() const; @@ -334,10 +335,10 @@ // return the size of this oop. This is used by the MarkSweep collector. int adjust_pointers(); -#ifndef SERIALGC +#if INCLUDE_ALL_GCS // Parallel old void update_header(ParCompactionManager* cm); -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS // mark-sweep support void follow_body(int begin, int end); @@ -354,7 +355,7 @@ ALL_OOP_OOP_ITERATE_CLOSURES_1(OOP_ITERATE_DECL) ALL_OOP_OOP_ITERATE_CLOSURES_2(OOP_ITERATE_DECL) -#ifndef SERIALGC +#if INCLUDE_ALL_GCS #define OOP_ITERATE_BACKWARDS_DECL(OopClosureType, nv_suffix) \ int oop_iterate_backwards(OopClosureType* blk); diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/oops/oop.inline.hpp --- a/src/share/vm/oops/oop.inline.hpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/oops/oop.inline.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -40,6 +40,7 @@ #include "oops/oop.hpp" #include "runtime/atomic.hpp" #include "runtime/os.hpp" +#include "utilities/macros.hpp" #ifdef TARGET_ARCH_x86 # include "bytes_x86.hpp" #endif @@ -227,12 +228,12 @@ // might not be the same as oop. inline narrowOop oopDesc::encode_klass_not_null(Klass* v) { - assert(!is_null(v), "oop value can never be zero"); + assert(!is_null(v), "klass value can never be zero"); assert(check_klass_alignment(v), "Address not aligned"); address base = Universe::narrow_klass_base(); int shift = Universe::narrow_klass_shift(); uint64_t pd = (uint64_t)(pointer_delta((void*)v, (void*)base, 1)); - assert(OopEncodingHeapMax > pd, "change encoding max if new encoding"); + assert(KlassEncodingMetaspaceMax > pd, "change encoding max if new encoding"); uint64_t result = pd >> shift; assert((result & CONST64(0xffffffff00000000)) == 0, "narrow klass pointer overflow"); assert(decode_klass(result) == v, "reversibility"); @@ -760,7 +761,7 @@ ALL_OOP_OOP_ITERATE_CLOSURES_1(OOP_ITERATE_DEFN) ALL_OOP_OOP_ITERATE_CLOSURES_2(OOP_ITERATE_DEFN) -#ifndef SERIALGC +#if INCLUDE_ALL_GCS #define OOP_ITERATE_BACKWARDS_DEFN(OopClosureType, nv_suffix) \ \ inline int oopDesc::oop_iterate_backwards(OopClosureType* blk) { \ @@ -770,6 +771,6 @@ ALL_OOP_OOP_ITERATE_CLOSURES_1(OOP_ITERATE_BACKWARDS_DEFN) ALL_OOP_OOP_ITERATE_CLOSURES_2(OOP_ITERATE_BACKWARDS_DEFN) -#endif // !SERIALGC +#endif // INCLUDE_ALL_GCS #endif // SHARE_VM_OOPS_OOP_INLINE_HPP diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/oops/oop.pcgc.inline.hpp --- a/src/share/vm/oops/oop.pcgc.inline.hpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/oops/oop.pcgc.inline.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -25,14 +25,15 @@ #ifndef SHARE_VM_OOPS_OOP_PCGC_INLINE_HPP #define SHARE_VM_OOPS_OOP_PCGC_INLINE_HPP -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/parNew/parNewGeneration.hpp" #include "gc_implementation/parallelScavenge/parallelScavengeHeap.hpp" #include "gc_implementation/parallelScavenge/psCompactionManager.hpp" #include "gc_implementation/parallelScavenge/psParallelCompact.hpp" #include "gc_implementation/parallelScavenge/psScavenge.hpp" #include "gc_implementation/parallelScavenge/psScavenge.inline.hpp" -#endif +#endif // INCLUDE_ALL_GCS inline void oopDesc::update_contents(ParCompactionManager* cm) { // The klass field must be updated before anything else diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/oops/oop.psgc.inline.hpp --- a/src/share/vm/oops/oop.psgc.inline.hpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/oops/oop.psgc.inline.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -25,11 +25,12 @@ #ifndef SHARE_VM_OOPS_OOP_PSGC_INLINE_HPP #define SHARE_VM_OOPS_OOP_PSGC_INLINE_HPP -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/parallelScavenge/parallelScavengeHeap.hpp" #include "gc_implementation/parallelScavenge/psScavenge.hpp" #include "gc_implementation/parallelScavenge/psScavenge.inline.hpp" -#endif +#endif // INCLUDE_ALL_GCS // ParallelScavengeHeap methods diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/oops/symbol.cpp --- a/src/share/vm/oops/symbol.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/oops/symbol.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -152,6 +152,7 @@ } void Symbol::print_symbol_on(outputStream* st) const { + ResourceMark rm; st = st ? st : tty; st->print("%s", as_quoted_ascii()); } diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/oops/typeArrayKlass.cpp --- a/src/share/vm/oops/typeArrayKlass.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/oops/typeArrayKlass.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -39,6 +39,7 @@ #include "oops/typeArrayKlass.hpp" #include "oops/typeArrayOop.hpp" #include "runtime/handles.inline.hpp" +#include "utilities/macros.hpp" bool TypeArrayKlass::compute_is_subtype_of(Klass* k) { if (!k->oop_is_typeArray()) { @@ -208,13 +209,13 @@ // know that Universe::TypeArrayKlass never moves. } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS void TypeArrayKlass::oop_follow_contents(ParCompactionManager* cm, oop obj) { assert(obj->is_typeArray(),"must be a type array"); // Performance tweak: We skip iterating over the klass pointer since we // know that Universe::TypeArrayKlass never moves. } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS int TypeArrayKlass::oop_adjust_pointers(oop obj) { assert(obj->is_typeArray(),"must be a type array"); @@ -240,7 +241,7 @@ return t->object_size(); } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS void TypeArrayKlass::oop_push_contents(PSPromotionManager* pm, oop obj) { ShouldNotReachHere(); assert(obj->is_typeArray(),"must be a type array"); @@ -251,7 +252,7 @@ assert(obj->is_typeArray(),"must be a type array"); return typeArrayOop(obj)->object_size(); } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS void TypeArrayKlass::initialize(TRAPS) { // Nothing to do. Having this function is handy since objArrayKlasses can be diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/opto/bytecodeInfo.cpp --- a/src/share/vm/opto/bytecodeInfo.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/opto/bytecodeInfo.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -47,7 +47,8 @@ _site_invoke_ratio(site_invoke_ratio), _max_inline_level(max_inline_level), _count_inline_bcs(method()->code_size_for_inlining()), - _subtrees(c->comp_arena(), 2, 0, NULL) + _subtrees(c->comp_arena(), 2, 0, NULL), + _msg(NULL) { NOT_PRODUCT(_count_inlines = 0;) if (_caller_jvms != NULL) { @@ -77,7 +78,8 @@ _method(callee_method), _site_invoke_ratio(site_invoke_ratio), _max_inline_level(max_inline_level), - _count_inline_bcs(method()->code_size()) + _count_inline_bcs(method()->code_size()), + _msg(NULL) { NOT_PRODUCT(_count_inlines = 0;) assert(!UseOldInlining, "do not use for old stuff"); @@ -95,8 +97,10 @@ ); } -// positive filter: should callee be inlined? returns NULL, if yes, or rejection msg -const char* InlineTree::should_inline(ciMethod* callee_method, ciMethod* caller_method, int caller_bci, ciCallProfile& profile, WarmCallInfo* wci_result) const { +// positive filter: should callee be inlined? +bool InlineTree::should_inline(ciMethod* callee_method, ciMethod* caller_method, + int caller_bci, ciCallProfile& profile, + WarmCallInfo* wci_result) { // Allows targeted inlining if(callee_method->should_inline()) { *wci_result = *(WarmCallInfo::always_hot()); @@ -104,11 +108,10 @@ CompileTask::print_inline_indent(inline_level()); tty->print_cr("Inlined method is hot: "); } - return NULL; + set_msg("force inline by CompilerOracle"); + return true; } - // positive filter: should send be inlined? returns NULL (--> yes) - // or rejection msg int size = callee_method->code_size_for_inlining(); // Check for too many throws (and not too huge) @@ -119,11 +122,13 @@ CompileTask::print_inline_indent(inline_level()); tty->print_cr("Inlined method with many throws (throws=%d):", callee_method->interpreter_throwout_count()); } - return NULL; + set_msg("many throws"); + return true; } if (!UseOldInlining) { - return NULL; // size and frequency are represented in a new way + set_msg("!UseOldInlining"); + return true; // size and frequency are represented in a new way } int default_max_inline_size = C->max_inline_size(); @@ -153,31 +158,44 @@ // Not hot. Check for medium-sized pre-existing nmethod at cold sites. if (callee_method->has_compiled_code() && callee_method->instructions_size() > inline_small_code_size) - return "already compiled into a medium method"; + set_msg("already compiled into a medium method"); + return false; } if (size > max_inline_size) { - if (max_inline_size > default_max_inline_size) - return "hot method too big"; - return "too big"; + if (max_inline_size > default_max_inline_size) { + set_msg("hot method too big"); + } else { + set_msg("too big"); + } + return false; } - return NULL; + return true; } -// negative filter: should callee NOT be inlined? returns NULL, ok to inline, or rejection msg -const char* InlineTree::should_not_inline(ciMethod *callee_method, ciMethod* caller_method, WarmCallInfo* wci_result) const { - // negative filter: should send NOT be inlined? returns NULL (--> inline) or rejection msg +// negative filter: should callee NOT be inlined? +bool InlineTree::should_not_inline(ciMethod *callee_method, + ciMethod* caller_method, + WarmCallInfo* wci_result) { + + const char* fail_msg = NULL; + + // First check all inlining restrictions which are required for correctness + if ( callee_method->is_abstract()) { + fail_msg = "abstract method"; // // note: we allow ik->is_abstract() + } else if (!callee_method->holder()->is_initialized()) { + fail_msg = "method holder not initialized"; + } else if ( callee_method->is_native()) { + fail_msg = "native method"; + } else if ( callee_method->dont_inline()) { + fail_msg = "don't inline by annotation"; + } + if (!UseOldInlining) { - const char* fail = NULL; - if ( callee_method->is_abstract()) fail = "abstract method"; - // note: we allow ik->is_abstract() - if (!callee_method->holder()->is_initialized()) fail = "method holder not initialized"; - if ( callee_method->is_native()) fail = "native method"; - if ( callee_method->dont_inline()) fail = "don't inline by annotation"; - - if (fail) { + if (fail_msg != NULL) { *wci_result = *(WarmCallInfo::always_cold()); - return fail; + set_msg(fail_msg); + return true; } if (callee_method->has_unloaded_classes_in_signature()) { @@ -199,20 +217,23 @@ // %%% adjust wci_result->size()? } - return NULL; + return false; + } + + // one more inlining restriction + if (fail_msg == NULL && callee_method->has_unloaded_classes_in_signature()) { + fail_msg = "unloaded signature classes"; } - // First check all inlining restrictions which are required for correctness - if ( callee_method->is_abstract()) return "abstract method"; - // note: we allow ik->is_abstract() - if (!callee_method->holder()->is_initialized()) return "method holder not initialized"; - if ( callee_method->is_native()) return "native method"; - if ( callee_method->dont_inline()) return "don't inline by annotation"; - if ( callee_method->has_unloaded_classes_in_signature()) return "unloaded signature classes"; + if (fail_msg != NULL) { + set_msg(fail_msg); + return true; + } + // ignore heuristic controls on inlining if (callee_method->should_inline()) { - // ignore heuristic controls on inlining - return NULL; + set_msg("force inline by CompilerOracle"); + return false; } if (callee_method->should_not_inline()) { return "disallowed by CompilerOracle"; @@ -223,7 +244,8 @@ if (!callee_method->force_inline()) { if (callee_method->has_compiled_code() && callee_method->instructions_size() > InlineSmallCode) { - return "already compiled into a big method"; + set_msg("already compiled into a big method"); + return true; } } @@ -234,17 +256,21 @@ const InlineTree *top = this; while (top->caller_tree() != NULL) top = top->caller_tree(); ciInstanceKlass* k = top->method()->holder(); - if (!k->is_subclass_of(C->env()->Throwable_klass())) - return "exception method"; + if (!k->is_subclass_of(C->env()->Throwable_klass())) { + set_msg("exception method"); + return true; + } } if (callee_method->should_not_inline()) { - return "disallowed by CompilerOracle"; + set_msg("disallowed by CompilerOracle"); + return true; } #ifndef PRODUCT if (ciReplay::should_not_inline(callee_method)) { - return "disallowed by ciReplay"; + set_msg("disallowed by ciReplay"); + return true; } #endif @@ -252,19 +278,23 @@ // Do not inline StringCache::profile() method used only at the beginning. if (callee_method->name() == ciSymbol::profile_name() && callee_method->holder()->name() == ciSymbol::java_lang_StringCache()) { - return "profiling method"; + set_msg("profiling method"); + return true; } } // use frequency-based objections only for non-trivial methods - if (callee_method->code_size() <= MaxTrivialSize) return NULL; + if (callee_method->code_size() <= MaxTrivialSize) { + return false; + } // don't use counts with -Xcomp or CTW if (UseInterpreter && !CompileTheWorld) { if (!callee_method->has_compiled_code() && !callee_method->was_executed_more_than(0)) { - return "never executed"; + set_msg("never executed"); + return true; } if (is_init_with_ea(callee_method, caller_method, C)) { @@ -273,39 +303,44 @@ } else if (!callee_method->was_executed_more_than(MIN2(MinInliningThreshold, CompileThreshold >> 1))) { - return "executed < MinInliningThreshold times"; + set_msg("executed < MinInliningThreshold times"); + return true; } } - return NULL; + return false; } //-----------------------------try_to_inline----------------------------------- -// return NULL if ok, reason for not inlining otherwise +// return true if ok // Relocated from "InliningClosure::try_to_inline" -const char* InlineTree::try_to_inline(ciMethod* callee_method, ciMethod* caller_method, int caller_bci, ciCallProfile& profile, WarmCallInfo* wci_result, bool& should_delay) { - // Old algorithm had funny accumulating BC-size counters +bool InlineTree::try_to_inline(ciMethod* callee_method, ciMethod* caller_method, + int caller_bci, ciCallProfile& profile, + WarmCallInfo* wci_result, bool& should_delay) { + + // Old algorithm had funny accumulating BC-size counters if (UseOldInlining && ClipInlining && (int)count_inline_bcs() >= DesiredMethodLimit) { if (!callee_method->force_inline() || !IncrementalInline) { - return "size > DesiredMethodLimit"; + set_msg("size > DesiredMethodLimit"); + return false; } else if (!C->inlining_incrementally()) { should_delay = true; } } - const char *msg = NULL; - msg = should_inline(callee_method, caller_method, caller_bci, profile, wci_result); - if (msg != NULL) - return msg; - - msg = should_not_inline(callee_method, caller_method, wci_result); - if (msg != NULL) - return msg; + if (!should_inline(callee_method, caller_method, caller_bci, profile, + wci_result)) { + return false; + } + if (should_not_inline(callee_method, caller_method, wci_result)) { + return false; + } if (InlineAccessors && callee_method->is_accessor()) { // accessor methods are not subject to any of the following limits. - return NULL; + set_msg("accessor"); + return true; } // suppress a few checks for accessors and trivial methods @@ -315,7 +350,8 @@ if (C->over_inlining_cutoff()) { if ((!callee_method->force_inline() && !caller_method->is_compiled_lambda_form()) || !IncrementalInline) { - return "NodeCountInliningCutoff"; + set_msg("NodeCountInliningCutoff"); + return false; } else { should_delay = true; } @@ -329,16 +365,19 @@ } else if (profile.count() == 0) { // don't inline unreached call sites - return "call site not reached"; + set_msg("call site not reached"); + return false; } } if (!C->do_inlining() && InlineAccessors) { - return "not an accessor"; + set_msg("not an accessor"); + return false; } if (inline_level() > _max_inline_level) { if (!callee_method->force_inline() || !IncrementalInline) { - return "inlining too deep"; + set_msg("inlining too deep"); + return false; } else if (!C->inlining_incrementally()) { should_delay = true; } @@ -348,15 +387,19 @@ if (!callee_method->is_compiled_lambda_form()) { // count the current method and the callee int inline_level = (method() == callee_method) ? 1 : 0; - if (inline_level > MaxRecursiveInlineLevel) - return "recursively inlining too deep"; + if (inline_level > MaxRecursiveInlineLevel) { + set_msg("recursively inlining too deep"); + return false; + } // count callers of current method and callee JVMState* jvms = caller_jvms(); while (jvms != NULL && jvms->has_method()) { if (jvms->method() == callee_method) { inline_level++; - if (inline_level > MaxRecursiveInlineLevel) - return "recursively inlining too deep"; + if (inline_level > MaxRecursiveInlineLevel) { + set_msg("recursively inlining too deep"); + return false; + } } jvms = jvms->caller(); } @@ -367,14 +410,15 @@ if (UseOldInlining && ClipInlining && (int)count_inline_bcs() + size >= DesiredMethodLimit) { if (!callee_method->force_inline() || !IncrementalInline) { - return "size > DesiredMethodLimit"; + set_msg("size > DesiredMethodLimit"); + return false; } else if (!C->inlining_incrementally()) { should_delay = true; } } // ok, inline this method - return NULL; + return true; } //------------------------------pass_initial_checks---------------------------- @@ -423,14 +467,25 @@ } //------------------------------print_inlining--------------------------------- -// Really, the failure_msg can be a success message also. -void InlineTree::print_inlining(ciMethod* callee_method, int caller_bci, const char* failure_msg) const { - C->print_inlining(callee_method, inline_level(), caller_bci, failure_msg ? failure_msg : "inline"); - if (callee_method == NULL) tty->print(" callee not monotonic or profiled"); - if (Verbose && callee_method) { - const InlineTree *top = this; - while( top->caller_tree() != NULL ) { top = top->caller_tree(); } - //tty->print(" bcs: %d+%d invoked: %d", top->count_inline_bcs(), callee_method->code_size(), callee_method->interpreter_invocation_count()); +void InlineTree::print_inlining(ciMethod* callee_method, int caller_bci, + bool success) const { + const char* inline_msg = msg(); + assert(inline_msg != NULL, "just checking"); + if (C->log() != NULL) { + if (success) { + C->log()->inline_success(inline_msg); + } else { + C->log()->inline_fail(inline_msg); + } + } + if (PrintInlining) { + C->print_inlining(callee_method, inline_level(), caller_bci, inline_msg); + if (callee_method == NULL) tty->print(" callee not monotonic or profiled"); + if (Verbose && callee_method) { + const InlineTree *top = this; + while( top->caller_tree() != NULL ) { top = top->caller_tree(); } + //tty->print(" bcs: %d+%d invoked: %d", top->count_inline_bcs(), callee_method->code_size(), callee_method->interpreter_invocation_count()); + } } } @@ -448,48 +503,50 @@ } assert(_method == jvms->method(), "redundant instance state"); #endif - const char *failure_msg = NULL; int caller_bci = jvms->bci(); - ciMethod *caller_method = jvms->method(); + ciMethod* caller_method = jvms->method(); // Do some initial checks. if (!pass_initial_checks(caller_method, caller_bci, callee_method)) { - if (PrintInlining) print_inlining(callee_method, caller_bci, "failed initial checks"); + set_msg("failed initial checks"); + print_inlining(callee_method, caller_bci, false /* !success */); return NULL; } // Do some parse checks. - failure_msg = check_can_parse(callee_method); - if (failure_msg != NULL) { - if (PrintInlining) print_inlining(callee_method, caller_bci, failure_msg); + set_msg(check_can_parse(callee_method)); + if (msg() != NULL) { + print_inlining(callee_method, caller_bci, false /* !success */); return NULL; } // Check if inlining policy says no. WarmCallInfo wci = *(initial_wci); - failure_msg = try_to_inline(callee_method, caller_method, caller_bci, profile, &wci, should_delay); - if (failure_msg != NULL && C->log() != NULL) { - C->log()->inline_fail(failure_msg); - } + bool success = try_to_inline(callee_method, caller_method, caller_bci, + profile, &wci, should_delay); #ifndef PRODUCT if (UseOldInlining && InlineWarmCalls && (PrintOpto || PrintOptoInlining || PrintInlining)) { bool cold = wci.is_cold(); bool hot = !cold && wci.is_hot(); - bool old_cold = (failure_msg != NULL); + bool old_cold = !success; if (old_cold != cold || (Verbose || WizardMode)) { + if (msg() == NULL) { + set_msg("OK"); + } tty->print(" OldInlining= %4s : %s\n WCI=", - old_cold ? "cold" : "hot", failure_msg ? failure_msg : "OK"); + old_cold ? "cold" : "hot", msg()); wci.print(); } } #endif if (UseOldInlining) { - if (failure_msg == NULL) + if (success) { wci = *(WarmCallInfo::always_hot()); - else + } else { wci = *(WarmCallInfo::always_cold()); + } } if (!InlineWarmCalls) { if (!wci.is_cold() && !wci.is_hot()) { @@ -499,11 +556,11 @@ } if (!wci.is_cold()) { - // In -UseOldInlining, the failure_msg may also be a success message. - if (failure_msg == NULL) failure_msg = "inline (hot)"; - // Inline! - if (PrintInlining) print_inlining(callee_method, caller_bci, failure_msg); + if (msg() == NULL) { + set_msg("inline (hot)"); + } + print_inlining(callee_method, caller_bci, true /* success */); if (UseOldInlining) build_inline_tree_for_callee(callee_method, jvms, caller_bci); if (InlineWarmCalls && !wci.is_hot()) @@ -512,8 +569,10 @@ } // Do not inline - if (failure_msg == NULL) failure_msg = "too cold to inline"; - if (PrintInlining) print_inlining(callee_method, caller_bci, failure_msg); + if (msg() == NULL) { + set_msg("too cold to inline"); + } + print_inlining(callee_method, caller_bci, false /* !success */ ); return NULL; } diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/opto/c2_globals.hpp --- a/src/share/vm/opto/c2_globals.hpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/opto/c2_globals.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -618,6 +618,9 @@ \ product(intx, LiveNodeCountInliningCutoff, 20000, \ "max number of live nodes in a method") \ + \ + diagnostic(bool, OptimizeExpensiveOps, true, \ + "Find best control for expensive operations") \ C2_FLAGS(DECLARE_DEVELOPER_FLAG, DECLARE_PD_DEVELOPER_FLAG, DECLARE_PRODUCT_FLAG, DECLARE_PD_PRODUCT_FLAG, DECLARE_DIAGNOSTIC_FLAG, DECLARE_EXPERIMENTAL_FLAG, DECLARE_NOTPRODUCT_FLAG) diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/opto/callGenerator.cpp --- a/src/share/vm/opto/callGenerator.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/opto/callGenerator.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -305,11 +305,13 @@ void LateInlineCallGenerator::do_late_inline() { // Can't inline it if (call_node() == NULL || call_node()->outcnt() == 0 || - call_node()->in(0) == NULL || call_node()->in(0)->is_top()) + call_node()->in(0) == NULL || call_node()->in(0)->is_top()) { return; + } + const TypeTuple *r = call_node()->tf()->domain(); for (int i1 = 0; i1 < method()->arg_size(); i1++) { - if (call_node()->in(TypeFunc::Parms + i1)->is_top()) { + if (call_node()->in(TypeFunc::Parms + i1)->is_top() && r->field_at(TypeFunc::Parms + i1) != Type::HALF) { assert(Compile::current()->inlining_incrementally(), "shouldn't happen during parsing"); return; } diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/opto/compile.cpp --- a/src/share/vm/opto/compile.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/opto/compile.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -409,6 +409,13 @@ remove_macro_node(n); } } + // Remove useless expensive node + for (int i = C->expensive_count()-1; i >= 0; i--) { + Node* n = C->expensive_node(i); + if (!useful.member(n)) { + remove_expensive_node(n); + } + } // clean up the late inline lists remove_useless_late_inlines(&_string_late_inlines, useful); remove_useless_late_inlines(&_late_inlines, useful); @@ -1061,6 +1068,7 @@ _intrinsics = NULL; _macro_nodes = new(comp_arena()) GrowableArray(comp_arena(), 8, 0, NULL); _predicate_opaqs = new(comp_arena()) GrowableArray(comp_arena(), 8, 0, NULL); + _expensive_nodes = new(comp_arena()) GrowableArray(comp_arena(), 8, 0, NULL); register_library_intrinsics(); } @@ -1927,6 +1935,10 @@ if (failing()) return; + // No more new expensive nodes will be added to the list from here + // so keep only the actual candidates for optimizations. + cleanup_expensive_nodes(igvn); + // Perform escape analysis if (_do_escape_analysis && ConnectionGraph::has_candidates(this)) { if (has_loops()) { @@ -3010,6 +3022,15 @@ return true; } + // Expensive nodes have their control input set to prevent the GVN + // from freely commoning them. There's no GVN beyond this point so + // no need to keep the control input. We want the expensive nodes to + // be freely moved to the least frequent code path by gcm. + assert(OptimizeExpensiveOps || expensive_count() == 0, "optimization off but list non empty?"); + for (int i = 0; i < expensive_count(); i++) { + _expensive_nodes->at(i)->set_req(0, NULL); + } + Final_Reshape_Counts frc; // Visit everybody reachable! @@ -3525,3 +3546,126 @@ } } } + +int Compile::cmp_expensive_nodes(Node* n1, Node* n2) { + if (n1->Opcode() < n2->Opcode()) return -1; + else if (n1->Opcode() > n2->Opcode()) return 1; + + assert(n1->req() == n2->req(), err_msg_res("can't compare %s nodes: n1->req() = %d, n2->req() = %d", NodeClassNames[n1->Opcode()], n1->req(), n2->req())); + for (uint i = 1; i < n1->req(); i++) { + if (n1->in(i) < n2->in(i)) return -1; + else if (n1->in(i) > n2->in(i)) return 1; + } + + return 0; +} + +int Compile::cmp_expensive_nodes(Node** n1p, Node** n2p) { + Node* n1 = *n1p; + Node* n2 = *n2p; + + return cmp_expensive_nodes(n1, n2); +} + +void Compile::sort_expensive_nodes() { + if (!expensive_nodes_sorted()) { + _expensive_nodes->sort(cmp_expensive_nodes); + } +} + +bool Compile::expensive_nodes_sorted() const { + for (int i = 1; i < _expensive_nodes->length(); i++) { + if (cmp_expensive_nodes(_expensive_nodes->adr_at(i), _expensive_nodes->adr_at(i-1)) < 0) { + return false; + } + } + return true; +} + +bool Compile::should_optimize_expensive_nodes(PhaseIterGVN &igvn) { + if (_expensive_nodes->length() == 0) { + return false; + } + + assert(OptimizeExpensiveOps, "optimization off?"); + + // Take this opportunity to remove dead nodes from the list + int j = 0; + for (int i = 0; i < _expensive_nodes->length(); i++) { + Node* n = _expensive_nodes->at(i); + if (!n->is_unreachable(igvn)) { + assert(n->is_expensive(), "should be expensive"); + _expensive_nodes->at_put(j, n); + j++; + } + } + _expensive_nodes->trunc_to(j); + + // Then sort the list so that similar nodes are next to each other + // and check for at least two nodes of identical kind with same data + // inputs. + sort_expensive_nodes(); + + for (int i = 0; i < _expensive_nodes->length()-1; i++) { + if (cmp_expensive_nodes(_expensive_nodes->adr_at(i), _expensive_nodes->adr_at(i+1)) == 0) { + return true; + } + } + + return false; +} + +void Compile::cleanup_expensive_nodes(PhaseIterGVN &igvn) { + if (_expensive_nodes->length() == 0) { + return; + } + + assert(OptimizeExpensiveOps, "optimization off?"); + + // Sort to bring similar nodes next to each other and clear the + // control input of nodes for which there's only a single copy. + sort_expensive_nodes(); + + int j = 0; + int identical = 0; + int i = 0; + for (; i < _expensive_nodes->length()-1; i++) { + assert(j <= i, "can't write beyond current index"); + if (_expensive_nodes->at(i)->Opcode() == _expensive_nodes->at(i+1)->Opcode()) { + identical++; + _expensive_nodes->at_put(j++, _expensive_nodes->at(i)); + continue; + } + if (identical > 0) { + _expensive_nodes->at_put(j++, _expensive_nodes->at(i)); + identical = 0; + } else { + Node* n = _expensive_nodes->at(i); + igvn.hash_delete(n); + n->set_req(0, NULL); + igvn.hash_insert(n); + } + } + if (identical > 0) { + _expensive_nodes->at_put(j++, _expensive_nodes->at(i)); + } else if (_expensive_nodes->length() >= 1) { + Node* n = _expensive_nodes->at(i); + igvn.hash_delete(n); + n->set_req(0, NULL); + igvn.hash_insert(n); + } + _expensive_nodes->trunc_to(j); +} + +void Compile::add_expensive_node(Node * n) { + assert(!_expensive_nodes->contains(n), "duplicate entry in expensive list"); + assert(n->is_expensive(), "expensive nodes with non-null control here only"); + assert(!n->is_CFG() && !n->is_Mem(), "no cfg or memory nodes here"); + if (OptimizeExpensiveOps) { + _expensive_nodes->append(n); + } else { + // Clear control input and let IGVN optimize expensive nodes if + // OptimizeExpensiveOps is off. + n->set_req(0, NULL); + } +} diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/opto/compile.hpp --- a/src/share/vm/opto/compile.hpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/opto/compile.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -314,6 +314,7 @@ GrowableArray* _intrinsics; // List of intrinsics. GrowableArray* _macro_nodes; // List of nodes which need to be expanded before matching. GrowableArray* _predicate_opaqs; // List of Opaque1 nodes for the loop predicates. + GrowableArray* _expensive_nodes; // List of nodes that are expensive to compute and that we'd better not let the GVN freely common ConnectionGraph* _congraph; #ifndef PRODUCT IdealGraphPrinter* _printer; @@ -398,6 +399,13 @@ GrowableArray* _print_inlining_list; int _print_inlining; + // Only keep nodes in the expensive node list that need to be optimized + void cleanup_expensive_nodes(PhaseIterGVN &igvn); + // Use for sorting expensive nodes to bring similar nodes together + static int cmp_expensive_nodes(Node** n1, Node** n2); + // Expensive nodes list already sorted? + bool expensive_nodes_sorted() const; + public: outputStream* print_inlining_stream() const { @@ -573,8 +581,10 @@ int macro_count() { return _macro_nodes->length(); } int predicate_count() { return _predicate_opaqs->length();} + int expensive_count() { return _expensive_nodes->length(); } Node* macro_node(int idx) { return _macro_nodes->at(idx); } Node* predicate_opaque1_node(int idx) { return _predicate_opaqs->at(idx);} + Node* expensive_node(int idx) { return _expensive_nodes->at(idx); } ConnectionGraph* congraph() { return _congraph;} void set_congraph(ConnectionGraph* congraph) { _congraph = congraph;} void add_macro_node(Node * n) { @@ -592,6 +602,12 @@ _predicate_opaqs->remove(n); } } + void add_expensive_node(Node * n); + void remove_expensive_node(Node * n) { + if (_expensive_nodes->contains(n)) { + _expensive_nodes->remove(n); + } + } void add_predicate_opaq(Node * n) { assert(!_predicate_opaqs->contains(n), " duplicate entry in predicate opaque1"); assert(_macro_nodes->contains(n), "should have already been in macro list"); @@ -604,6 +620,13 @@ return _predicate_opaqs->contains(n); } + // Are there candidate expensive nodes for optimization? + bool should_optimize_expensive_nodes(PhaseIterGVN &igvn); + // Check whether n1 and n2 are similar + static int cmp_expensive_nodes(Node* n1, Node* n2); + // Sort expensive nodes to locate similar expensive nodes + void sort_expensive_nodes(); + // Compilation environment. Arena* comp_arena() { return &_comp_arena; } ciEnv* env() const { return _env; } diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/opto/generateOptoStub.cpp --- a/src/share/vm/opto/generateOptoStub.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/opto/generateOptoStub.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -88,12 +88,12 @@ thread, in_bytes(JavaThread::frame_anchor_offset()) + in_bytes(JavaFrameAnchor::last_Java_pc_offset())); -#if defined(SPARC) || defined(IA64) +#if defined(SPARC) Node* adr_flags = basic_plus_adr(top(), thread, in_bytes(JavaThread::frame_anchor_offset()) + in_bytes(JavaFrameAnchor::flags_offset())); -#endif /* defined(SPARC) || defined(IA64) */ +#endif /* defined(SPARC) */ // Drop in the last_Java_sp. last_Java_fp is not touched. @@ -102,10 +102,8 @@ // users will look at the other fields. // Node *adr_sp = basic_plus_adr(top(), thread, in_bytes(JavaThread::last_Java_sp_offset())); -#ifndef IA64 Node *last_sp = basic_plus_adr(top(), frameptr(), (intptr_t) STACK_BIAS); store_to_memory(NULL, adr_sp, last_sp, T_ADDRESS, NoAlias); -#endif // Set _thread_in_native // The order of stores into TLS is critical! Setting _thread_in_native MUST @@ -210,19 +208,12 @@ //----------------------------- // Clear last_Java_sp -#ifdef IA64 - if( os::is_MP() ) insert_mem_bar(Op_MemBarRelease); -#endif - store_to_memory(NULL, adr_sp, null(), T_ADDRESS, NoAlias); -#ifdef IA64 - if (os::is_MP() && UseMembar) insert_mem_bar(new MemBarVolatileNode()); -#endif // def IA64 // Clear last_Java_pc and (optionally)_flags store_to_memory(NULL, adr_last_Java_pc, null(), T_ADDRESS, NoAlias); -#if defined(SPARC) || defined(IA64) +#if defined(SPARC) store_to_memory(NULL, adr_flags, intcon(0), T_INT, NoAlias); -#endif /* defined(SPARC) || defined(IA64) */ +#endif /* defined(SPARC) */ #ifdef IA64 Node* adr_last_Java_fp = basic_plus_adr(top(), thread, in_bytes(JavaThread::last_Java_fp_offset())); if( os::is_MP() ) insert_mem_bar(Op_MemBarRelease); diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/opto/library_call.cpp --- a/src/share/vm/opto/library_call.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/opto/library_call.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -1481,10 +1481,10 @@ Node* arg = round_double_node(argument(0)); Node* n; switch (id) { - case vmIntrinsics::_dabs: n = new (C) AbsDNode( arg); break; - case vmIntrinsics::_dsqrt: n = new (C) SqrtDNode(0, arg); break; - case vmIntrinsics::_dlog: n = new (C) LogDNode( arg); break; - case vmIntrinsics::_dlog10: n = new (C) Log10DNode( arg); break; + case vmIntrinsics::_dabs: n = new (C) AbsDNode( arg); break; + case vmIntrinsics::_dsqrt: n = new (C) SqrtDNode(C, control(), arg); break; + case vmIntrinsics::_dlog: n = new (C) LogDNode(C, control(), arg); break; + case vmIntrinsics::_dlog10: n = new (C) Log10DNode(C, control(), arg); break; default: fatal_unexpected_iid(id); break; } set_result(_gvn.transform(n)); @@ -1499,9 +1499,9 @@ Node* n = NULL; switch (id) { - case vmIntrinsics::_dsin: n = new (C) SinDNode(arg); break; - case vmIntrinsics::_dcos: n = new (C) CosDNode(arg); break; - case vmIntrinsics::_dtan: n = new (C) TanDNode(arg); break; + case vmIntrinsics::_dsin: n = new (C) SinDNode(C, control(), arg); break; + case vmIntrinsics::_dcos: n = new (C) CosDNode(C, control(), arg); break; + case vmIntrinsics::_dtan: n = new (C) TanDNode(C, control(), arg); break; default: fatal_unexpected_iid(id); break; } n = _gvn.transform(n); @@ -1653,7 +1653,7 @@ // really odd corner cases (+/- Infinity). Just uncommon-trap them. bool LibraryCallKit::inline_exp() { Node* arg = round_double_node(argument(0)); - Node* n = _gvn.transform(new (C) ExpDNode(0, arg)); + Node* n = _gvn.transform(new (C) ExpDNode(C, control(), arg)); finish_pow_exp(n, arg, NULL, OptoRuntime::Math_D_D_Type(), CAST_FROM_FN_PTR(address, SharedRuntime::dexp), "EXP"); @@ -1688,7 +1688,7 @@ if (!too_many_traps(Deoptimization::Reason_intrinsic)) { // Short form: skip the fancy tests and just check for NaN result. - result = _gvn.transform(new (C) PowDNode(0, x, y)); + result = _gvn.transform(new (C) PowDNode(C, control(), x, y)); } else { // If this inlining ever returned NaN in the past, include all // checks + call to the runtime. @@ -1715,7 +1715,7 @@ Node *complex_path = _gvn.transform( new (C) IfTrueNode(if1) ); // Set fast path result - Node *fast_result = _gvn.transform( new (C) PowDNode(0, x, y) ); + Node *fast_result = _gvn.transform( new (C) PowDNode(C, control(), x, y) ); phi->init_req(3, fast_result); // Complex path @@ -1775,7 +1775,7 @@ // abs(x) Node *absx=_gvn.transform( new (C) AbsDNode(x)); // abs(x)^y - Node *absxpowy = _gvn.transform( new (C) PowDNode(0, absx, y) ); + Node *absxpowy = _gvn.transform( new (C) PowDNode(C, control(), absx, y) ); // -abs(x)^y Node *negabsxpowy = _gvn.transform(new (C) NegDNode (absxpowy)); // (1&(long)y)==1?-DPow(abs(x), y):DPow(abs(x), y) diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/opto/loopnode.cpp --- a/src/share/vm/opto/loopnode.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/opto/loopnode.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -88,9 +88,9 @@ assert( !n->is_Phi() && !n->is_CFG(), "this code only handles data nodes" ); uint i; Node *early; - if( n->in(0) ) { + if (n->in(0) && !n->is_expensive()) { early = n->in(0); - if( !early->is_CFG() ) // Might be a non-CFG multi-def + if (!early->is_CFG()) // Might be a non-CFG multi-def early = get_ctrl(early); // So treat input as a straight data input i = 1; } else { @@ -99,28 +99,28 @@ } uint e_d = dom_depth(early); assert( early, "" ); - for( ; i < n->req(); i++ ) { + for (; i < n->req(); i++) { Node *cin = get_ctrl(n->in(i)); assert( cin, "" ); // Keep deepest dominator depth uint c_d = dom_depth(cin); - if( c_d > e_d ) { // Deeper guy? + if (c_d > e_d) { // Deeper guy? early = cin; // Keep deepest found so far e_d = c_d; - } else if( c_d == e_d && // Same depth? - early != cin ) { // If not equal, must use slower algorithm + } else if (c_d == e_d && // Same depth? + early != cin) { // If not equal, must use slower algorithm // If same depth but not equal, one _must_ dominate the other // and we want the deeper (i.e., dominated) guy. Node *n1 = early; Node *n2 = cin; - while( 1 ) { + while (1) { n1 = idom(n1); // Walk up until break cycle n2 = idom(n2); - if( n1 == cin || // Walked early up to cin - dom_depth(n2) < c_d ) + if (n1 == cin || // Walked early up to cin + dom_depth(n2) < c_d) break; // early is deeper; keep him - if( n2 == early || // Walked cin up to early - dom_depth(n1) < c_d ) { + if (n2 == early || // Walked cin up to early + dom_depth(n1) < c_d) { early = cin; // cin is deeper; keep him break; } @@ -132,9 +132,108 @@ // Return earliest legal location assert(early == find_non_split_ctrl(early), "unexpected early control"); + if (n->is_expensive()) { + assert(n->in(0), "should have control input"); + early = get_early_ctrl_for_expensive(n, early); + } + return early; } +//------------------------------get_early_ctrl_for_expensive--------------------------------- +// Move node up the dominator tree as high as legal while still beneficial +Node *PhaseIdealLoop::get_early_ctrl_for_expensive(Node *n, Node* earliest) { + assert(n->in(0) && n->is_expensive(), "expensive node with control input here"); + assert(OptimizeExpensiveOps, "optimization off?"); + + Node* ctl = n->in(0); + assert(ctl->is_CFG(), "expensive input 0 must be cfg"); + uint min_dom_depth = dom_depth(earliest); +#ifdef ASSERT + if (!is_dominator(ctl, earliest) && !is_dominator(earliest, ctl)) { + dump_bad_graph("Bad graph detected in get_early_ctrl_for_expensive", n, earliest, ctl); + assert(false, "Bad graph detected in get_early_ctrl_for_expensive"); + } +#endif + if (dom_depth(ctl) < min_dom_depth) { + return earliest; + } + + while (1) { + Node *next = ctl; + // Moving the node out of a loop on the projection of a If + // confuses loop predication. So once we hit a Loop in a If branch + // that doesn't branch to an UNC, we stop. The code that process + // expensive nodes will notice the loop and skip over it to try to + // move the node further up. + if (ctl->is_CountedLoop() && ctl->in(1) != NULL && ctl->in(1)->in(0) != NULL && ctl->in(1)->in(0)->is_If()) { + if (!is_uncommon_trap_if_pattern(ctl->in(1)->as_Proj(), Deoptimization::Reason_none)) { + break; + } + next = idom(ctl->in(1)->in(0)); + } else if (ctl->is_Proj()) { + // We only move it up along a projection if the projection is + // the single control projection for its parent: same code path, + // if it's a If with UNC or fallthrough of a call. + Node* parent_ctl = ctl->in(0); + if (parent_ctl == NULL) { + break; + } else if (parent_ctl->is_CountedLoopEnd() && parent_ctl->as_CountedLoopEnd()->loopnode() != NULL) { + next = parent_ctl->as_CountedLoopEnd()->loopnode()->init_control(); + } else if (parent_ctl->is_If()) { + if (!is_uncommon_trap_if_pattern(ctl->as_Proj(), Deoptimization::Reason_none)) { + break; + } + assert(idom(ctl) == parent_ctl, "strange"); + next = idom(parent_ctl); + } else if (ctl->is_CatchProj()) { + if (ctl->as_Proj()->_con != CatchProjNode::fall_through_index) { + break; + } + assert(parent_ctl->in(0)->in(0)->is_Call(), "strange graph"); + next = parent_ctl->in(0)->in(0)->in(0); + } else { + // Check if parent control has a single projection (this + // control is the only possible successor of the parent + // control). If so, we can try to move the node above the + // parent control. + int nb_ctl_proj = 0; + for (DUIterator_Fast imax, i = parent_ctl->fast_outs(imax); i < imax; i++) { + Node *p = parent_ctl->fast_out(i); + if (p->is_Proj() && p->is_CFG()) { + nb_ctl_proj++; + if (nb_ctl_proj > 1) { + break; + } + } + } + + if (nb_ctl_proj > 1) { + break; + } + assert(parent_ctl->is_Start() || parent_ctl->is_MemBar() || parent_ctl->is_Call(), "unexpected node"); + assert(idom(ctl) == parent_ctl, "strange"); + next = idom(parent_ctl); + } + } else { + next = idom(ctl); + } + if (next->is_Root() || next->is_Start() || dom_depth(next) < min_dom_depth) { + break; + } + ctl = next; + } + + if (ctl != n->in(0)) { + _igvn.hash_delete(n); + n->set_req(0, ctl); + _igvn.hash_insert(n); + } + + return ctl; +} + + //------------------------------set_early_ctrl--------------------------------- // Set earliest legal control void PhaseIdealLoop::set_early_ctrl( Node *n ) { @@ -1892,6 +1991,98 @@ } } +//------------------------process_expensive_nodes----------------------------- +// Expensive nodes have their control input set to prevent the GVN +// from commoning them and as a result forcing the resulting node to +// be in a more frequent path. Use CFG information here, to change the +// control inputs so that some expensive nodes can be commoned while +// not executed more frequently. +bool PhaseIdealLoop::process_expensive_nodes() { + assert(OptimizeExpensiveOps, "optimization off?"); + + // Sort nodes to bring similar nodes together + C->sort_expensive_nodes(); + + bool progress = false; + + for (int i = 0; i < C->expensive_count(); ) { + Node* n = C->expensive_node(i); + int start = i; + // Find nodes similar to n + i++; + for (; i < C->expensive_count() && Compile::cmp_expensive_nodes(n, C->expensive_node(i)) == 0; i++); + int end = i; + // And compare them two by two + for (int j = start; j < end; j++) { + Node* n1 = C->expensive_node(j); + if (is_node_unreachable(n1)) { + continue; + } + for (int k = j+1; k < end; k++) { + Node* n2 = C->expensive_node(k); + if (is_node_unreachable(n2)) { + continue; + } + + assert(n1 != n2, "should be pair of nodes"); + + Node* c1 = n1->in(0); + Node* c2 = n2->in(0); + + Node* parent_c1 = c1; + Node* parent_c2 = c2; + + // The call to get_early_ctrl_for_expensive() moves the + // expensive nodes up but stops at loops that are in a if + // branch. See whether we can exit the loop and move above the + // If. + if (c1->is_Loop()) { + parent_c1 = c1->in(1); + } + if (c2->is_Loop()) { + parent_c2 = c2->in(1); + } + + if (parent_c1 == parent_c2) { + _igvn._worklist.push(n1); + _igvn._worklist.push(n2); + continue; + } + + // Look for identical expensive node up the dominator chain. + if (is_dominator(c1, c2)) { + c2 = c1; + } else if (is_dominator(c2, c1)) { + c1 = c2; + } else if (parent_c1->is_Proj() && parent_c1->in(0)->is_If() && + parent_c2->is_Proj() && parent_c1->in(0) == parent_c2->in(0)) { + // Both branches have the same expensive node so move it up + // before the if. + c1 = c2 = idom(parent_c1->in(0)); + } + // Do the actual moves + if (n1->in(0) != c1) { + _igvn.hash_delete(n1); + n1->set_req(0, c1); + _igvn.hash_insert(n1); + _igvn._worklist.push(n1); + progress = true; + } + if (n2->in(0) != c2) { + _igvn.hash_delete(n2); + n2->set_req(0, c2); + _igvn.hash_insert(n2); + _igvn._worklist.push(n2); + progress = true; + } + } + } + } + + return progress; +} + + //============================================================================= //----------------------------build_and_optimize------------------------------- // Create a PhaseLoop. Build the ideal Loop tree. Map each Ideal Node to @@ -1960,7 +2151,9 @@ } // Nothing to do, so get out - if( !C->has_loops() && !skip_loop_opts && !do_split_ifs && !_verify_me && !_verify_only ) { + bool stop_early = !C->has_loops() && !skip_loop_opts && !do_split_ifs && !_verify_me && !_verify_only; + bool do_expensive_nodes = C->should_optimize_expensive_nodes(_igvn); + if (stop_early && !do_expensive_nodes) { _igvn.optimize(); // Cleanup NeverBranches return; } @@ -2058,6 +2251,21 @@ return; } + if (stop_early) { + assert(do_expensive_nodes, "why are we here?"); + if (process_expensive_nodes()) { + // If we made some progress when processing expensive nodes then + // the IGVN may modify the graph in a way that will allow us to + // make some more progress: we need to try processing expensive + // nodes again. + C->set_major_progress(); + } + + _igvn.optimize(); + + return; + } + // Some parser-inserted loop predicates could never be used by loop // predication or they were moved away from loop during some optimizations. // For example, peeling. Eliminate them before next loop optimizations. @@ -2120,6 +2328,10 @@ NOT_PRODUCT( if( VerifyLoopOptimizations ) verify(); ); } + if (!C->major_progress() && do_expensive_nodes && process_expensive_nodes()) { + C->set_major_progress(); + } + // Perform loop predication before iteration splitting if (C->has_loops() && !C->major_progress() && (C->predicate_count() > 0)) { _ltree_root->_child->loop_predication(this); @@ -3299,7 +3511,7 @@ #ifdef ASSERT if (legal->is_Start() && !early->is_Root()) { // Bad graph. Print idom path and fail. - dump_bad_graph(n, early, LCA); + dump_bad_graph("Bad graph detected in build_loop_late", n, early, LCA); assert(false, "Bad graph detected in build_loop_late"); } #endif @@ -3350,8 +3562,8 @@ } #ifdef ASSERT -void PhaseIdealLoop::dump_bad_graph(Node* n, Node* early, Node* LCA) { - tty->print_cr( "Bad graph detected in build_loop_late"); +void PhaseIdealLoop::dump_bad_graph(const char* msg, Node* n, Node* early, Node* LCA) { + tty->print_cr(msg); tty->print("n: "); n->dump(); tty->print("early(n): "); early->dump(); if (n->in(0) != NULL && !n->in(0)->is_top() && diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/opto/loopnode.hpp --- a/src/share/vm/opto/loopnode.hpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/opto/loopnode.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -263,9 +263,18 @@ bool stride_is_con() const { Node *tmp = stride (); return (tmp != NULL && tmp->is_Con()); } BoolTest::mask test_trip() const { return in(TestValue)->as_Bool()->_test._test; } CountedLoopNode *loopnode() const { + // The CountedLoopNode that goes with this CountedLoopEndNode may + // have been optimized out by the IGVN so be cautious with the + // pattern matching on the graph + if (phi() == NULL) { + return NULL; + } Node *ln = phi()->in(0); - assert( ln->Opcode() == Op_CountedLoop, "malformed loop" ); - return (CountedLoopNode*)ln; } + if (ln->is_CountedLoop() && ln->as_CountedLoop()->loopexit() == this) { + return (CountedLoopNode*)ln; + } + return NULL; + } #ifndef PRODUCT virtual void dump_spec(outputStream *st) const; @@ -598,6 +607,7 @@ // check if transform created new nodes that need _ctrl recorded Node *get_late_ctrl( Node *n, Node *early ); Node *get_early_ctrl( Node *n ); + Node *get_early_ctrl_for_expensive(Node *n, Node* earliest); void set_early_ctrl( Node *n ); void set_subtree_ctrl( Node *root ); void set_ctrl( Node *n, Node *ctrl ) { @@ -905,6 +915,16 @@ void collect_potentially_useful_predicates(IdealLoopTree *loop, Unique_Node_List &predicate_opaque1); void eliminate_useless_predicates(); + // Change the control input of expensive nodes to allow commoning by + // IGVN when it is guaranteed to not result in a more frequent + // execution of the expensive node. Return true if progress. + bool process_expensive_nodes(); + + // Check whether node has become unreachable + bool is_node_unreachable(Node *n) const { + return !has_node(n) || n->is_unreachable(_igvn); + } + // Eliminate range-checks and other trip-counter vs loop-invariant tests. void do_range_check( IdealLoopTree *loop, Node_List &old_new ); @@ -1043,7 +1063,7 @@ void register_new_node( Node *n, Node *blk ); #ifdef ASSERT -void dump_bad_graph(Node* n, Node* early, Node* LCA); + void dump_bad_graph(const char* msg, Node* n, Node* early, Node* LCA); #endif #ifndef PRODUCT diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/opto/memnode.cpp --- a/src/share/vm/opto/memnode.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/opto/memnode.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -320,6 +320,9 @@ if (mem != old_mem) { set_req(MemNode::Memory, mem); + if (can_reshape && old_mem->outcnt() == 0) { + igvn->_worklist.push(old_mem); + } if (phase->type( mem ) == Type::TOP) return NodeSentinel; return this; } @@ -2319,9 +2322,9 @@ if (ReduceFieldZeroing && /*can_reshape &&*/ mem->is_Proj() && mem->in(0)->is_Initialize()) { InitializeNode* init = mem->in(0)->as_Initialize(); - intptr_t offset = init->can_capture_store(this, phase); + intptr_t offset = init->can_capture_store(this, phase, can_reshape); if (offset > 0) { - Node* moved = init->capture_store(this, offset, phase); + Node* moved = init->capture_store(this, offset, phase, can_reshape); // If the InitializeNode captured me, it made a raw copy of me, // and I need to disappear. if (moved != NULL) { @@ -3134,7 +3137,7 @@ // an initialization. Returns zero if a check fails. // On success, returns the (constant) offset to which the store applies, // within the initialized memory. -intptr_t InitializeNode::can_capture_store(StoreNode* st, PhaseTransform* phase) { +intptr_t InitializeNode::can_capture_store(StoreNode* st, PhaseTransform* phase, bool can_reshape) { const int FAIL = 0; if (st->req() != MemNode::ValueIn + 1) return FAIL; // an inscrutable StoreNode (card mark?) @@ -3156,6 +3159,91 @@ if (!detect_init_independence(val, true, complexity_count)) return FAIL; // stored value must be 'simple enough' + // The Store can be captured only if nothing after the allocation + // and before the Store is using the memory location that the store + // overwrites. + bool failed = false; + // If is_complete_with_arraycopy() is true the shape of the graph is + // well defined and is safe so no need for extra checks. + if (!is_complete_with_arraycopy()) { + // We are going to look at each use of the memory state following + // the allocation to make sure nothing reads the memory that the + // Store writes. + const TypePtr* t_adr = phase->type(adr)->isa_ptr(); + int alias_idx = phase->C->get_alias_index(t_adr); + ResourceMark rm; + Unique_Node_List mems; + mems.push(mem); + Node* unique_merge = NULL; + for (uint next = 0; next < mems.size(); ++next) { + Node *m = mems.at(next); + for (DUIterator_Fast jmax, j = m->fast_outs(jmax); j < jmax; j++) { + Node *n = m->fast_out(j); + if (n->outcnt() == 0) { + continue; + } + if (n == st) { + continue; + } else if (n->in(0) != NULL && n->in(0) != ctl) { + // If the control of this use is different from the control + // of the Store which is right after the InitializeNode then + // this node cannot be between the InitializeNode and the + // Store. + continue; + } else if (n->is_MergeMem()) { + if (n->as_MergeMem()->memory_at(alias_idx) == m) { + // We can hit a MergeMemNode (that will likely go away + // later) that is a direct use of the memory state + // following the InitializeNode on the same slice as the + // store node that we'd like to capture. We need to check + // the uses of the MergeMemNode. + mems.push(n); + } + } else if (n->is_Mem()) { + Node* other_adr = n->in(MemNode::Address); + if (other_adr == adr) { + failed = true; + break; + } else { + const TypePtr* other_t_adr = phase->type(other_adr)->isa_ptr(); + if (other_t_adr != NULL) { + int other_alias_idx = phase->C->get_alias_index(other_t_adr); + if (other_alias_idx == alias_idx) { + // A load from the same memory slice as the store right + // after the InitializeNode. We check the control of the + // object/array that is loaded from. If it's the same as + // the store control then we cannot capture the store. + assert(!n->is_Store(), "2 stores to same slice on same control?"); + Node* base = other_adr; + assert(base->is_AddP(), err_msg_res("should be addp but is %s", base->Name())); + base = base->in(AddPNode::Base); + if (base != NULL) { + base = base->uncast(); + if (base->is_Proj() && base->in(0) == alloc) { + failed = true; + break; + } + } + } + } + } + } else { + failed = true; + break; + } + } + } + } + if (failed) { + if (!can_reshape) { + // We decided we couldn't capture the store during parsing. We + // should try again during the next IGVN once the graph is + // cleaner. + phase->C->record_for_igvn(st); + } + return FAIL; + } + return offset; // success } @@ -3266,11 +3354,11 @@ // rawstore1 rawstore2) // Node* InitializeNode::capture_store(StoreNode* st, intptr_t start, - PhaseTransform* phase) { + PhaseTransform* phase, bool can_reshape) { assert(stores_are_sane(phase), ""); if (start < 0) return NULL; - assert(can_capture_store(st, phase) == start, "sanity"); + assert(can_capture_store(st, phase, can_reshape) == start, "sanity"); Compile* C = phase->C; int size_in_bytes = st->memory_size(); diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/opto/memnode.hpp --- a/src/share/vm/opto/memnode.hpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/opto/memnode.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -1072,11 +1072,11 @@ // See if this store can be captured; return offset where it initializes. // Return 0 if the store cannot be moved (any sort of problem). - intptr_t can_capture_store(StoreNode* st, PhaseTransform* phase); + intptr_t can_capture_store(StoreNode* st, PhaseTransform* phase, bool can_reshape); // Capture another store; reformat it to write my internal raw memory. // Return the captured copy, else NULL if there is some sort of problem. - Node* capture_store(StoreNode* st, intptr_t start, PhaseTransform* phase); + Node* capture_store(StoreNode* st, intptr_t start, PhaseTransform* phase, bool can_reshape); // Find captured store which corresponds to the range [start..start+size). // Return my own memory projection (meaning the initial zero bits) diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/opto/node.cpp --- a/src/share/vm/opto/node.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/opto/node.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -493,6 +493,8 @@ } if (is_macro()) compile->add_macro_node(n); + if (is_expensive()) + compile->add_expensive_node(n); n->set_idx(compile->next_unique()); // Get new unique index as well debug_only( n->verify_construction() ); @@ -616,6 +618,9 @@ if (is_macro()) { compile->remove_macro_node(this); } + if (is_expensive()) { + compile->remove_expensive_node(this); + } #ifdef ASSERT // We will not actually delete the storage, but we'll make the node unusable. *(address*)this = badAddress; // smash the C++ vtbl, probably @@ -689,6 +694,13 @@ } #endif + +//------------------------------is_unreachable--------------------------------- +bool Node::is_unreachable(PhaseIterGVN &igvn) const { + assert(!is_Mach(), "doesn't work with MachNodes"); + return outcnt() == 0 || igvn.type(this) == Type::TOP || in(0)->is_top(); +} + //------------------------------add_req---------------------------------------- // Add a new required input at the end void Node::add_req( Node *n ) { @@ -1246,6 +1258,10 @@ if (dead->is_macro()) { igvn->C->remove_macro_node(dead); } + if (dead->is_expensive()) { + igvn->C->remove_expensive_node(dead); + } + igvn->C->record_dead_node(dead->_idx); // Kill all inputs to the dead guy for (uint i=0; i < dead->req(); i++) { Node *n = dead->in(i); // Get input to dead guy diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/opto/node.hpp --- a/src/share/vm/opto/node.hpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/opto/node.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -378,6 +378,8 @@ bool is_dead() const; #define is_not_dead(n) ((n) == NULL || !VerifyIterativeGVN || !((n)->is_dead())) #endif + // Check whether node has become unreachable + bool is_unreachable(PhaseIterGVN &igvn) const; // Set a required input edge, also updates corresponding output edge void add_req( Node *n ); // Append a NEW required input @@ -646,7 +648,8 @@ Flag_may_be_short_branch = Flag_is_dead_loop_safe << 1, Flag_avoid_back_to_back = Flag_may_be_short_branch << 1, Flag_has_call = Flag_avoid_back_to_back << 1, - _max_flags = (Flag_has_call << 1) - 1 // allow flags combination + Flag_is_expensive = Flag_has_call << 1, + _max_flags = (Flag_is_expensive << 1) - 1 // allow flags combination }; private: @@ -819,6 +822,8 @@ // The node is a "macro" node which needs to be expanded before matching bool is_macro() const { return (_flags & Flag_is_macro) != 0; } + // The node is expensive: the best control is set during loop opts + bool is_expensive() const { return (_flags & Flag_is_expensive) != 0 && in(0) != NULL; } //----------------- Optimization diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/opto/parse.hpp --- a/src/share/vm/opto/parse.hpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/opto/parse.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -58,7 +58,7 @@ GrowableArray _subtrees; void print_impl(outputStream* stj, int indent) const PRODUCT_RETURN; - + const char* _msg; protected: InlineTree(Compile* C, const InlineTree* caller_tree, @@ -70,16 +70,29 @@ InlineTree *build_inline_tree_for_callee(ciMethod* callee_method, JVMState* caller_jvms, int caller_bci); - const char* try_to_inline(ciMethod* callee_method, ciMethod* caller_method, int caller_bci, ciCallProfile& profile, WarmCallInfo* wci_result, bool& should_delay); - const char* should_inline(ciMethod* callee_method, ciMethod* caller_method, int caller_bci, ciCallProfile& profile, WarmCallInfo* wci_result) const; - const char* should_not_inline(ciMethod* callee_method, ciMethod* caller_method, WarmCallInfo* wci_result) const; - void print_inlining(ciMethod *callee_method, int caller_bci, const char *failure_msg) const; + bool try_to_inline(ciMethod* callee_method, + ciMethod* caller_method, + int caller_bci, + ciCallProfile& profile, + WarmCallInfo* wci_result, + bool& should_delay); + bool should_inline(ciMethod* callee_method, + ciMethod* caller_method, + int caller_bci, + ciCallProfile& profile, + WarmCallInfo* wci_result); + bool should_not_inline(ciMethod* callee_method, + ciMethod* caller_method, + WarmCallInfo* wci_result); + void print_inlining(ciMethod* callee_method, int caller_bci, + bool success) const; - InlineTree *caller_tree() const { return _caller_tree; } + InlineTree* caller_tree() const { return _caller_tree; } InlineTree* callee_at(int bci, ciMethod* m) const; int inline_level() const { return stack_depth(); } int stack_depth() const { return _caller_jvms ? _caller_jvms->depth() : 0; } - + const char* msg() const { return _msg; } + void set_msg(const char* msg) { _msg = msg; } public: static const char* check_can_parse(ciMethod* callee); diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/opto/parse3.cpp --- a/src/share/vm/opto/parse3.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/opto/parse3.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -487,7 +487,8 @@ fun, NULL, TypeRawPtr::BOTTOM, makecon(TypeKlassPtr::make(array_klass)), length[0], length[1], length[2], - length[3], length[4]); + (ndimensions > 2) ? length[3] : NULL, + (ndimensions > 3) ? length[4] : NULL); } else { // Create a java array for dimension sizes Node* dims = NULL; diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/opto/phaseX.cpp --- a/src/share/vm/opto/phaseX.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/opto/phaseX.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -1197,12 +1197,27 @@ assert(!(i < imax), "sanity"); } } + if (ReduceFieldZeroing && dead->is_Load() && i == MemNode::Memory && + in->is_Proj() && in->in(0) != NULL && in->in(0)->is_Initialize()) { + // A Load that directly follows an InitializeNode is + // going away. The Stores that follow are candidates + // again to be captured by the InitializeNode. + for (DUIterator_Fast jmax, j = in->fast_outs(jmax); j < jmax; j++) { + Node *n = in->fast_out(j); + if (n->is_Store()) { + _worklist.push(n); + } + } + } } } C->record_dead_node(dead->_idx); if (dead->is_macro()) { C->remove_macro_node(dead); } + if (dead->is_expensive()) { + C->remove_expensive_node(dead); + } if (recurse) { continue; diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/opto/regmask.cpp --- a/src/share/vm/opto/regmask.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/opto/regmask.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -241,7 +241,8 @@ } else { // Else its a split-pair case if( bit != _A[i] ) return false; // Found many bits, so fail i++; // Skip iteration forward - if( _A[i] != 1 ) return false; // Require 1 lo bit in next word + if( i >= RM_SIZE || _A[i] != 1 ) + return false; // Require 1 lo bit in next word } } } @@ -254,7 +255,7 @@ // Find the lowest-numbered register set in the mask. Return the // HIGHEST register number in the set, or BAD if no sets. // Works also for size 1. -OptoReg::Name RegMask::find_first_set(int size) const { +OptoReg::Name RegMask::find_first_set(const int size) const { verify_sets(size); for (int i = 0; i < RM_SIZE; i++) { if (_A[i]) { // Found some bits @@ -268,7 +269,7 @@ //------------------------------clear_to_sets---------------------------------- // Clear out partial bits; leave only aligned adjacent bit pairs -void RegMask::clear_to_sets(int size) { +void RegMask::clear_to_sets(const int size) { if (size == 1) return; assert(2 <= size && size <= 8, "update low bits table"); assert(is_power_of_2(size), "sanity"); @@ -293,7 +294,7 @@ //------------------------------smear_to_sets---------------------------------- // Smear out partial bits to aligned adjacent bit sets -void RegMask::smear_to_sets(int size) { +void RegMask::smear_to_sets(const int size) { if (size == 1) return; assert(2 <= size && size <= 8, "update low bits table"); assert(is_power_of_2(size), "sanity"); @@ -318,7 +319,7 @@ } //------------------------------is_aligned_set-------------------------------- -bool RegMask::is_aligned_sets(int size) const { +bool RegMask::is_aligned_sets(const int size) const { if (size == 1) return true; assert(2 <= size && size <= 8, "update low bits table"); assert(is_power_of_2(size), "sanity"); @@ -344,7 +345,7 @@ //------------------------------is_bound_set----------------------------------- // Return TRUE if the mask contains one adjacent set of bits and no other bits. // Works also for size 1. -int RegMask::is_bound_set(int size) const { +int RegMask::is_bound_set(const int size) const { if( is_AllStack() ) return false; assert(1 <= size && size <= 8, "update low bits table"); int bit = -1; // Set to hold the one bit allowed @@ -352,7 +353,7 @@ if (_A[i] ) { // Found some bits if (bit != -1) return false; // Already had bits, so fail - bit = _A[i] & -_A[i]; // Extract 1 bit from mask + bit = _A[i] & -_A[i]; // Extract low bit from mask int hi_bit = bit << (size-1); // high bit if (hi_bit != 0) { // Bit set stays in same word? int set = hi_bit + ((hi_bit-1) & ~(bit-1)); @@ -362,12 +363,12 @@ if (((-1) & ~(bit-1)) != _A[i]) return false; // Found many bits, so fail i++; // Skip iteration forward and check high part - assert(size <= 8, "update next code"); // The lower 24 bits should be 0 since it is split case and size <= 8. int set = bit>>24; set = set & -set; // Remove sign extension. set = (((set << size) - 1) >> 8); - if (_A[i] != set) return false; // Require 1 lo bit in next word + if (i >= RM_SIZE || _A[i] != set) + return false; // Require expected low bits in next word } } } diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/opto/regmask.hpp --- a/src/share/vm/opto/regmask.hpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/opto/regmask.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -225,22 +225,22 @@ // Find the lowest-numbered register set in the mask. Return the // HIGHEST register number in the set, or BAD if no sets. // Assert that the mask contains only bit sets. - OptoReg::Name find_first_set(int size) const; + OptoReg::Name find_first_set(const int size) const; // Clear out partial bits; leave only aligned adjacent bit sets of size. - void clear_to_sets(int size); + void clear_to_sets(const int size); // Smear out partial bits to aligned adjacent bit sets. - void smear_to_sets(int size); + void smear_to_sets(const int size); // Verify that the mask contains only aligned adjacent bit sets void verify_sets(int size) const { assert(is_aligned_sets(size), "mask is not aligned, adjacent sets"); } // Test that the mask contains only aligned adjacent bit sets - bool is_aligned_sets(int size) const; + bool is_aligned_sets(const int size) const; // mask is a set of misaligned registers bool is_misaligned_set(int size) const { return (int)Size()==size && !is_aligned_sets(size);} // Test for a single adjacent set - int is_bound_set(int size) const; + int is_bound_set(const int size) const; static bool is_vector(uint ireg); static int num_registers(uint ireg); diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/opto/subnode.hpp --- a/src/share/vm/opto/subnode.hpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/opto/subnode.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -399,7 +399,10 @@ // Cosinus of a double class CosDNode : public Node { public: - CosDNode( Node *in1 ) : Node(0, in1) {} + CosDNode(Compile* C, Node *c, Node *in1) : Node(c, in1) { + init_flags(Flag_is_expensive); + C->add_expensive_node(this); + } virtual int Opcode() const; const Type *bottom_type() const { return Type::DOUBLE; } virtual uint ideal_reg() const { return Op_RegD; } @@ -410,7 +413,10 @@ // Sinus of a double class SinDNode : public Node { public: - SinDNode( Node *in1 ) : Node(0, in1) {} + SinDNode(Compile* C, Node *c, Node *in1) : Node(c, in1) { + init_flags(Flag_is_expensive); + C->add_expensive_node(this); + } virtual int Opcode() const; const Type *bottom_type() const { return Type::DOUBLE; } virtual uint ideal_reg() const { return Op_RegD; } @@ -422,7 +428,10 @@ // tangens of a double class TanDNode : public Node { public: - TanDNode(Node *in1 ) : Node(0, in1) {} + TanDNode(Compile* C, Node *c,Node *in1) : Node(c, in1) { + init_flags(Flag_is_expensive); + C->add_expensive_node(this); + } virtual int Opcode() const; const Type *bottom_type() const { return Type::DOUBLE; } virtual uint ideal_reg() const { return Op_RegD; } @@ -445,7 +454,10 @@ // square root a double class SqrtDNode : public Node { public: - SqrtDNode(Node *c, Node *in1 ) : Node(c, in1) {} + SqrtDNode(Compile* C, Node *c, Node *in1) : Node(c, in1) { + init_flags(Flag_is_expensive); + C->add_expensive_node(this); + } virtual int Opcode() const; const Type *bottom_type() const { return Type::DOUBLE; } virtual uint ideal_reg() const { return Op_RegD; } @@ -456,7 +468,10 @@ // Exponentiate a double class ExpDNode : public Node { public: - ExpDNode( Node *c, Node *in1 ) : Node(c, in1) {} + ExpDNode(Compile* C, Node *c, Node *in1) : Node(c, in1) { + init_flags(Flag_is_expensive); + C->add_expensive_node(this); + } virtual int Opcode() const; const Type *bottom_type() const { return Type::DOUBLE; } virtual uint ideal_reg() const { return Op_RegD; } @@ -467,7 +482,10 @@ // Log_e of a double class LogDNode : public Node { public: - LogDNode( Node *in1 ) : Node(0, in1) {} + LogDNode(Compile* C, Node *c, Node *in1) : Node(c, in1) { + init_flags(Flag_is_expensive); + C->add_expensive_node(this); + } virtual int Opcode() const; const Type *bottom_type() const { return Type::DOUBLE; } virtual uint ideal_reg() const { return Op_RegD; } @@ -478,7 +496,10 @@ // Log_10 of a double class Log10DNode : public Node { public: - Log10DNode( Node *in1 ) : Node(0, in1) {} + Log10DNode(Compile* C, Node *c, Node *in1) : Node(c, in1) { + init_flags(Flag_is_expensive); + C->add_expensive_node(this); + } virtual int Opcode() const; const Type *bottom_type() const { return Type::DOUBLE; } virtual uint ideal_reg() const { return Op_RegD; } @@ -489,7 +510,10 @@ // Raise a double to a double power class PowDNode : public Node { public: - PowDNode(Node *c, Node *in1, Node *in2 ) : Node(c, in1, in2) {} + PowDNode(Compile* C, Node *c, Node *in1, Node *in2 ) : Node(c, in1, in2) { + init_flags(Flag_is_expensive); + C->add_expensive_node(this); + } virtual int Opcode() const; const Type *bottom_type() const { return Type::DOUBLE; } virtual uint ideal_reg() const { return Op_RegD; } diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/opto/superword.cpp --- a/src/share/vm/opto/superword.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/opto/superword.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -143,7 +143,8 @@ // Ready the block - construct_bb(); + if (!construct_bb()) + return; // Exit if no interesting nodes or complex graph. dependence_graph(); @@ -615,6 +616,7 @@ if (n == stop) break; preds.push(n); prev = n; + assert(n->is_Mem(), err_msg_res("unexpected node %s", n->Name())); n = n->in(MemNode::Memory); } } @@ -1578,7 +1580,7 @@ //------------------------------construct_bb--------------------------- // Construct reverse postorder list of block members -void SuperWord::construct_bb() { +bool SuperWord::construct_bb() { Node* entry = bb(); assert(_stk.length() == 0, "stk is empty"); @@ -1596,6 +1598,12 @@ Node *n = lpt()->_body.at(i); set_bb_idx(n, i); // Create a temporary map if (in_bb(n)) { + if (n->is_LoadStore() || n->is_MergeMem() || + (n->is_Proj() && !n->as_Proj()->is_CFG())) { + // Bailout if the loop has LoadStore, MergeMem or data Proj + // nodes. Superword optimization does not work with them. + return false; + } bb_ct++; if (!n->is_CFG()) { bool found = false; @@ -1620,6 +1628,10 @@ if (in_bb(n) && (n->is_Phi() && n->bottom_type() == Type::MEMORY)) { Node* n_tail = n->in(LoopNode::LoopBackControl); if (n_tail != n->in(LoopNode::EntryControl)) { + if (!n_tail->is_Mem()) { + assert(n_tail->is_Mem(), err_msg_res("unexpected node for memory slice: %s", n_tail->Name())); + return false; // Bailout + } _mem_slice_head.push(n); _mem_slice_tail.push(n_tail); } @@ -1695,6 +1707,7 @@ } #endif assert(rpo_idx == -1 && bb_ct == _block.length(), "all block members found"); + return (_mem_slice_head.length() > 0) || (_data_entry.length() > 0); } //------------------------------initialize_bb--------------------------- diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/opto/superword.hpp --- a/src/share/vm/opto/superword.hpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/opto/superword.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -380,7 +380,7 @@ // Is use->in(u_idx) a vector use? bool is_vector_use(Node* use, int u_idx); // Construct reverse postorder list of block members - void construct_bb(); + bool construct_bb(); // Initialize per node info void initialize_bb(); // Insert n into block after pos diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/precompiled/precompiled.hpp --- a/src/share/vm/precompiled/precompiled.hpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/precompiled/precompiled.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -24,6 +24,7 @@ // Precompiled headers are turned off for Sun Studion, // or if the user passes USE_PRECOMPILED_HEADER=0 to the makefiles. + #ifndef DONT_USE_PRECOMPILED_HEADER # include "asm/assembler.hpp" @@ -288,7 +289,7 @@ #ifdef GRAAL # include "graal/graalGlobals.hpp" #endif // GRAAL -#ifndef SERIALGC +#if INCLUDE_ALL_GCS # include "gc_implementation/concurrentMarkSweep/cmsOopClosures.hpp" # include "gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp" # include "gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp" @@ -317,6 +318,6 @@ # include "gc_implementation/shared/gcAdaptivePolicyCounters.hpp" # include "gc_implementation/shared/gcPolicyCounters.hpp" # include "gc_implementation/shared/parGCAllocBuffer.hpp" -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS #endif // !DONT_USE_PRECOMPILED_HEADER diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/prims/jni.cpp --- a/src/share/vm/prims/jni.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/prims/jni.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -32,12 +32,13 @@ #include "classfile/systemDictionary.hpp" #include "classfile/vmSymbols.hpp" #include "interpreter/linkResolver.hpp" +#include "utilities/macros.hpp" #ifdef GRAAL #include "graal/graalCompiler.hpp" #endif -#ifndef SERIALGC +#if INCLUDE_ALL_GCS #include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp" -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS #include "memory/allocation.hpp" #include "memory/allocation.inline.hpp" #include "memory/gcLocker.inline.hpp" @@ -2654,7 +2655,7 @@ o = JvmtiExport::jni_GetField_probe(thread, obj, o, k, fieldID, false); } jobject ret = JNIHandles::make_local(env, o->obj_field(offset)); -#ifndef SERIALGC +#if INCLUDE_ALL_GCS // If G1 is enabled and we are accessing the value of the referent // field in a reference object then we need to register a non-null // referent with the SATB barrier. @@ -2673,7 +2674,7 @@ G1SATBCardTableModRefBS::enqueue(referent); } } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS #ifndef USDT2 DTRACE_PROBE1(hotspot_jni, GetObjectField__return, ret); #else /* USDT2 */ diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/prims/jniCheck.hpp --- a/src/share/vm/prims/jniCheck.hpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/prims/jniCheck.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,9 +25,7 @@ #ifndef SHARE_VM_PRIMS_JNICHECK_HPP #define SHARE_VM_PRIMS_JNICHECK_HPP -#ifndef KERNEL #include "runtime/thread.hpp" -#endif extern "C" { // Report a JNI failure caught by -Xcheck:jni. Perform a core dump. diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/prims/jvm.cpp --- a/src/share/vm/prims/jvm.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/prims/jvm.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -1575,9 +1575,9 @@ if (!java_lang_Class::is_primitive(JNIHandles::resolve(cls))) { Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve(cls)); if (k->oop_is_instance()) { - Annotations* type_annotations = InstanceKlass::cast(k)->type_annotations(); + AnnotationArray* type_annotations = InstanceKlass::cast(k)->class_type_annotations(); if (type_annotations != NULL) { - typeArrayOop a = Annotations::make_java_array(type_annotations->class_annotations(), CHECK_NULL); + typeArrayOop a = Annotations::make_java_array(type_annotations, CHECK_NULL); return (jbyteArray) JNIHandles::make_local(env, a); } } @@ -1622,7 +1622,7 @@ // For a 0 index, give a NULL symbol Symbol* const sym = 0 != params[i].name_cp_index ? mh->constants()->symbol_at(params[i].name_cp_index) : NULL; - int flags = build_int_from_shorts(params[i].flags_lo, params[i].flags_hi); + int flags = params[i].flags; oop param = Reflection::new_parameter(reflected_method, i, sym, flags, CHECK_NULL); result->obj_at_put(i, param); @@ -2304,6 +2304,15 @@ JVM_END +JVM_QUICK_ENTRY(jboolean, JVM_IsVMGeneratedMethodIx(JNIEnv *env, jclass cls, int method_index)) + JVMWrapper("JVM_IsVMGeneratedMethodIx"); + ResourceMark rm(THREAD); + Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(cls)); + k = JvmtiThreadState::class_to_verify_considering_redefinition(k, thread); + Method* method = InstanceKlass::cast(k)->methods()->at(method_index); + return method->is_overpass(); +JVM_END + JVM_ENTRY(const char*, JVM_GetMethodIxNameUTF(JNIEnv *env, jclass cls, jint method_index)) JVMWrapper("JVM_GetMethodIxIxUTF"); Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(cls)); @@ -4521,10 +4530,5 @@ // consider to expose this new capability in the sun.rt.jvmCapabilities jvmstat // counter defined in runtimeService.cpp. info->is_attachable = AttachListener::is_attach_supported(); -#ifdef KERNEL - info->is_kernel_jvm = 1; // true; -#else // KERNEL - info->is_kernel_jvm = 0; // false; -#endif // KERNEL } JVM_END diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/prims/jvm.h --- a/src/share/vm/prims/jvm.h Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/prims/jvm.h Tue Mar 05 23:44:54 2013 +0100 @@ -860,6 +860,13 @@ JVM_IsConstructorIx(JNIEnv *env, jclass cb, int index); /* + * Is the given method generated by the VM. + * The method is identified by method_index. + */ +JNIEXPORT jboolean JNICALL +JVM_IsVMGeneratedMethodIx(JNIEnv *env, jclass cb, int index); + +/* * Returns the name of a given method in UTF format. * The result remains valid until JVM_ReleaseUTF is called. * @@ -1552,8 +1559,7 @@ * the new bit is also added in the main/baseline. */ unsigned int is_attachable : 1; - unsigned int is_kernel_jvm : 1; - unsigned int : 30; + unsigned int : 31; unsigned int : 32; unsigned int : 32; } jvm_version_info; diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/prims/jvmtiCodeBlobEvents.hpp --- a/src/share/vm/prims/jvmtiCodeBlobEvents.hpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/prims/jvmtiCodeBlobEvents.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,9 +25,7 @@ #ifndef SHARE_VM_PRIMS_JVMTICODEBLOBEVENTS_HPP #define SHARE_VM_PRIMS_JVMTICODEBLOBEVENTS_HPP -#ifndef JVMTI_KERNEL #include "jvmtifiles/jvmti.h" -#endif // forward declaration class JvmtiEnv; diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/prims/jvmtiEnv.cpp --- a/src/share/vm/prims/jvmtiEnv.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/prims/jvmtiEnv.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -647,8 +647,6 @@ return JVMTI_ERROR_NONE; } /* end GetJLocationFormat */ -#ifndef JVMTI_KERNEL - // // Thread functions // @@ -3436,5 +3434,3 @@ } return err; } /* end SetSystemProperty */ - -#endif // !JVMTI_KERNEL diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/prims/jvmtiEnvBase.cpp --- a/src/share/vm/prims/jvmtiEnvBase.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/prims/jvmtiEnvBase.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -74,10 +74,8 @@ JvmtiManageCapabilities::initialize(); -#ifndef JVMTI_KERNEL // register extension functions and events JvmtiExtensions::register_extensions(); -#endif // !JVMTI_KERNEL #ifdef JVMTI_TRACE JvmtiTrace::initialize(); @@ -236,14 +234,12 @@ // Same situation as with events (see above) set_native_method_prefixes(0, NULL); -#ifndef JVMTI_KERNEL JvmtiTagMap* tag_map_to_deallocate = _tag_map; set_tag_map(NULL); // A tag map can be big, deallocate it now if (tag_map_to_deallocate != NULL) { delete tag_map_to_deallocate; } -#endif // !JVMTI_KERNEL _needs_clean_up = true; } @@ -255,14 +251,12 @@ // There is a small window of time during which the tag map of a // disposed environment could have been reallocated. // Make sure it is gone. -#ifndef JVMTI_KERNEL JvmtiTagMap* tag_map_to_deallocate = _tag_map; set_tag_map(NULL); // A tag map can be big, deallocate it now if (tag_map_to_deallocate != NULL) { delete tag_map_to_deallocate; } -#endif // !JVMTI_KERNEL _magic = BAD_MAGIC; } @@ -593,8 +587,6 @@ return (jclass)jni_reference(k->java_mirror()); } -#ifndef JVMTI_KERNEL - // // Field Information // @@ -1482,5 +1474,3 @@ } } } - -#endif // !JVMTI_KERNEL diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/prims/jvmtiEnvBase.hpp --- a/src/share/vm/prims/jvmtiEnvBase.hpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/prims/jvmtiEnvBase.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -35,6 +35,7 @@ #include "runtime/thread.hpp" #include "runtime/vm_operations.hpp" #include "utilities/growableArray.hpp" +#include "utilities/macros.hpp" // // Forward Declarations diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/prims/jvmtiExport.cpp --- a/src/share/vm/prims/jvmtiExport.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/prims/jvmtiExport.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -50,9 +50,10 @@ #include "runtime/vframe.hpp" #include "services/attachListener.hpp" #include "services/serviceUtil.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/parallelScavenge/psMarkSweep.hpp" -#endif +#endif // INCLUDE_ALL_GCS #ifdef JVMTI_TRACE #define EVT_TRACE(evt,out) if ((JvmtiTrace::event_trace_flags(evt) & JvmtiTrace::SHOW_EVENT_SENT) != 0) { SafeResourceMark rm; tty->print_cr out; } @@ -677,7 +678,6 @@ } -#ifndef JVMTI_KERNEL static inline Klass* oop_to_klass(oop obj) { Klass* k = obj->klass(); @@ -2178,7 +2178,6 @@ typedef jint (JNICALL *OnAttachEntry_t)(JavaVM*, char *, void *); } -#ifndef SERVICES_KERNEL jint JvmtiExport::load_agent_library(AttachOperation* op, outputStream* st) { char ebuf[1024]; char buffer[JVM_MAXPATHLEN]; @@ -2259,7 +2258,6 @@ } return result; } -#endif // SERVICES_KERNEL //////////////////////////////////////////////////////////////////////////////////////////////// @@ -2457,4 +2455,3 @@ JvmtiExport::post_garbage_collection_finish(); } } -#endif // JVMTI_KERNEL diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/prims/jvmtiExport.hpp --- a/src/share/vm/prims/jvmtiExport.hpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/prims/jvmtiExport.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -34,6 +34,7 @@ #include "runtime/handles.hpp" #include "utilities/globalDefinitions.hpp" #include "utilities/growableArray.hpp" +#include "utilities/macros.hpp" // Must be included after jvmti.h. #include "code/jvmticmlr.h" diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/prims/jvmtiExtensions.hpp --- a/src/share/vm/prims/jvmtiExtensions.hpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/prims/jvmtiExtensions.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,11 +25,9 @@ #ifndef SHARE_VM_PRIMS_JVMTIEXTENSIONS_HPP #define SHARE_VM_PRIMS_JVMTIEXTENSIONS_HPP -#ifndef JVMTI_KERNEL #include "jvmtifiles/jvmti.h" #include "jvmtifiles/jvmtiEnv.hpp" #include "memory/allocation.hpp" -#endif // JvmtiExtensions // diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/prims/jvmtiImpl.cpp --- a/src/share/vm/prims/jvmtiImpl.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/prims/jvmtiImpl.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -905,8 +905,6 @@ #endif } -#ifndef KERNEL - JvmtiDeferredEvent JvmtiDeferredEvent::compiled_method_load_event( nmethod* nm) { JvmtiDeferredEvent event = JvmtiDeferredEvent(TYPE_COMPILED_METHOD_LOAD); @@ -1098,5 +1096,3 @@ } } } - -#endif // ndef KERNEL diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/prims/jvmtiImpl.hpp --- a/src/share/vm/prims/jvmtiImpl.hpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/prims/jvmtiImpl.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,8 +25,6 @@ #ifndef SHARE_VM_PRIMS_JVMTIIMPL_HPP #define SHARE_VM_PRIMS_JVMTIIMPL_HPP -#ifndef JVMTI_KERNEL - #include "classfile/systemDictionary.hpp" #include "jvmtifiles/jvmti.h" #include "oops/objArrayOop.hpp" @@ -435,7 +433,6 @@ static void print(); }; -#endif // !JVMTI_KERNEL /** * When a thread (such as the compiler thread or VM thread) cannot post a diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/prims/jvmtiRawMonitor.hpp --- a/src/share/vm/prims/jvmtiRawMonitor.hpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/prims/jvmtiRawMonitor.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,10 +25,8 @@ #ifndef SHARE_VM_PRIMS_JVMTIRAWMONITOR_HPP #define SHARE_VM_PRIMS_JVMTIRAWMONITOR_HPP -#ifndef JVMTI_KERNEL #include "runtime/objectMonitor.hpp" #include "utilities/growableArray.hpp" -#endif // // class JvmtiRawMonitor diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/prims/jvmtiRedefineClasses.cpp --- a/src/share/vm/prims/jvmtiRedefineClasses.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/prims/jvmtiRedefineClasses.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -23,6 +23,7 @@ */ #include "precompiled.hpp" +#include "classfile/metadataOnStackMark.hpp" #include "classfile/systemDictionary.hpp" #include "classfile/verifier.hpp" #include "code/codeCache.hpp" @@ -115,43 +116,6 @@ return true; } -// Keep track of marked on-stack metadata so it can be cleared. -GrowableArray* _marked_objects = NULL; -NOT_PRODUCT(bool MetadataOnStackMark::_is_active = false;) - -// Walk metadata on the stack and mark it so that redefinition doesn't delete -// it. Class unloading also walks the previous versions and might try to -// delete it, so this class is used by class unloading also. -MetadataOnStackMark::MetadataOnStackMark() { - assert(SafepointSynchronize::is_at_safepoint(), "sanity check"); - NOT_PRODUCT(_is_active = true;) - if (_marked_objects == NULL) { - _marked_objects = new (ResourceObj::C_HEAP, mtClass) GrowableArray(1000, true); - } - Threads::metadata_do(Metadata::mark_on_stack); - CodeCache::alive_nmethods_do(nmethod::mark_on_stack); - CompileBroker::mark_on_stack(); -} - -MetadataOnStackMark::~MetadataOnStackMark() { - assert(SafepointSynchronize::is_at_safepoint(), "sanity check"); - // Unmark everything that was marked. Can't do the same walk because - // redefine classes messes up the code cache so the set of methods - // might not be the same. - for (int i = 0; i< _marked_objects->length(); i++) { - _marked_objects->at(i)->set_on_stack(false); - } - _marked_objects->clear(); // reuse growable array for next time. - NOT_PRODUCT(_is_active = false;) -} - -// Record which objects are marked so we can unmark the same objects. -void MetadataOnStackMark::record(Metadata* m) { - assert(_is_active, "metadata on stack marking is active"); - _marked_objects->push(m); -} - - void VM_RedefineClasses::doit() { Thread *thread = Thread::current(); @@ -190,8 +154,15 @@ // See jvmtiExport.hpp for detailed explanation. JvmtiExport::set_has_redefined_a_class(); -#ifdef ASSERT - SystemDictionary::classes_do(check_class, thread); +// check_class() is optionally called for product bits, but is +// always called for non-product bits. +#ifdef PRODUCT + if (RC_TRACE_ENABLED(0x00004000)) { +#endif + RC_TRACE_WITH_THREAD(0x00004000, thread, ("calling check_class")); + SystemDictionary::classes_do(check_class, thread); +#ifdef PRODUCT + } #endif } @@ -314,76 +285,23 @@ case JVM_CONSTANT_NameAndType: { int name_ref_i = scratch_cp->name_ref_index_at(scratch_i); - int new_name_ref_i = 0; - bool match = (name_ref_i < *merge_cp_length_p) && - scratch_cp->compare_entry_to(name_ref_i, *merge_cp_p, name_ref_i, - THREAD); - if (!match) { - // forward reference in *merge_cp_p or not a direct match - - int found_i = scratch_cp->find_matching_entry(name_ref_i, *merge_cp_p, - THREAD); - if (found_i != 0) { - guarantee(found_i != name_ref_i, - "compare_entry_to() and find_matching_entry() do not agree"); - - // Found a matching entry somewhere else in *merge_cp_p so - // just need a mapping entry. - new_name_ref_i = found_i; - map_index(scratch_cp, name_ref_i, found_i); - } else { - // no match found so we have to append this entry to *merge_cp_p - append_entry(scratch_cp, name_ref_i, merge_cp_p, merge_cp_length_p, - THREAD); - // The above call to append_entry() can only append one entry - // so the post call query of *merge_cp_length_p is only for - // the sake of consistency. - new_name_ref_i = *merge_cp_length_p - 1; - } - } + int new_name_ref_i = find_or_append_indirect_entry(scratch_cp, name_ref_i, merge_cp_p, + merge_cp_length_p, THREAD); int signature_ref_i = scratch_cp->signature_ref_index_at(scratch_i); - int new_signature_ref_i = 0; - match = (signature_ref_i < *merge_cp_length_p) && - scratch_cp->compare_entry_to(signature_ref_i, *merge_cp_p, - signature_ref_i, THREAD); - if (!match) { - // forward reference in *merge_cp_p or not a direct match - - int found_i = scratch_cp->find_matching_entry(signature_ref_i, - *merge_cp_p, THREAD); - if (found_i != 0) { - guarantee(found_i != signature_ref_i, - "compare_entry_to() and find_matching_entry() do not agree"); - - // Found a matching entry somewhere else in *merge_cp_p so - // just need a mapping entry. - new_signature_ref_i = found_i; - map_index(scratch_cp, signature_ref_i, found_i); - } else { - // no match found so we have to append this entry to *merge_cp_p - append_entry(scratch_cp, signature_ref_i, merge_cp_p, - merge_cp_length_p, THREAD); - // The above call to append_entry() can only append one entry - // so the post call query of *merge_cp_length_p is only for - // the sake of consistency. - new_signature_ref_i = *merge_cp_length_p - 1; - } - } + int new_signature_ref_i = find_or_append_indirect_entry(scratch_cp, signature_ref_i, + merge_cp_p, merge_cp_length_p, + THREAD); // If the referenced entries already exist in *merge_cp_p, then // both new_name_ref_i and new_signature_ref_i will both be 0. // In that case, all we are appending is the current entry. - if (new_name_ref_i == 0) { - new_name_ref_i = name_ref_i; - } else { + if (new_name_ref_i != name_ref_i) { RC_TRACE(0x00080000, ("NameAndType entry@%d name_ref_index change: %d to %d", *merge_cp_length_p, name_ref_i, new_name_ref_i)); } - if (new_signature_ref_i == 0) { - new_signature_ref_i = signature_ref_i; - } else { + if (new_signature_ref_i != signature_ref_i) { RC_TRACE(0x00080000, ("NameAndType entry@%d signature_ref_index change: %d to %d", *merge_cp_length_p, signature_ref_i, new_signature_ref_i)); @@ -405,76 +323,12 @@ case JVM_CONSTANT_Methodref: { int klass_ref_i = scratch_cp->uncached_klass_ref_index_at(scratch_i); - int new_klass_ref_i = 0; - bool match = (klass_ref_i < *merge_cp_length_p) && - scratch_cp->compare_entry_to(klass_ref_i, *merge_cp_p, klass_ref_i, - THREAD); - if (!match) { - // forward reference in *merge_cp_p or not a direct match - - int found_i = scratch_cp->find_matching_entry(klass_ref_i, *merge_cp_p, - THREAD); - if (found_i != 0) { - guarantee(found_i != klass_ref_i, - "compare_entry_to() and find_matching_entry() do not agree"); - - // Found a matching entry somewhere else in *merge_cp_p so - // just need a mapping entry. - new_klass_ref_i = found_i; - map_index(scratch_cp, klass_ref_i, found_i); - } else { - // no match found so we have to append this entry to *merge_cp_p - append_entry(scratch_cp, klass_ref_i, merge_cp_p, merge_cp_length_p, - THREAD); - // The above call to append_entry() can only append one entry - // so the post call query of *merge_cp_length_p is only for - // the sake of consistency. Without the optimization where we - // use JVM_CONSTANT_UnresolvedClass, then up to two entries - // could be appended. - new_klass_ref_i = *merge_cp_length_p - 1; - } - } - - int name_and_type_ref_i = - scratch_cp->uncached_name_and_type_ref_index_at(scratch_i); - int new_name_and_type_ref_i = 0; - match = (name_and_type_ref_i < *merge_cp_length_p) && - scratch_cp->compare_entry_to(name_and_type_ref_i, *merge_cp_p, - name_and_type_ref_i, THREAD); - if (!match) { - // forward reference in *merge_cp_p or not a direct match - - int found_i = scratch_cp->find_matching_entry(name_and_type_ref_i, - *merge_cp_p, THREAD); - if (found_i != 0) { - guarantee(found_i != name_and_type_ref_i, - "compare_entry_to() and find_matching_entry() do not agree"); - - // Found a matching entry somewhere else in *merge_cp_p so - // just need a mapping entry. - new_name_and_type_ref_i = found_i; - map_index(scratch_cp, name_and_type_ref_i, found_i); - } else { - // no match found so we have to append this entry to *merge_cp_p - append_entry(scratch_cp, name_and_type_ref_i, merge_cp_p, - merge_cp_length_p, THREAD); - // The above call to append_entry() can append more than - // one entry so the post call query of *merge_cp_length_p - // is required in order to get the right index for the - // JVM_CONSTANT_NameAndType entry. - new_name_and_type_ref_i = *merge_cp_length_p - 1; - } - } - - // If the referenced entries already exist in *merge_cp_p, then - // both new_klass_ref_i and new_name_and_type_ref_i will both be - // 0. In that case, all we are appending is the current entry. - if (new_klass_ref_i == 0) { - new_klass_ref_i = klass_ref_i; - } - if (new_name_and_type_ref_i == 0) { - new_name_and_type_ref_i = name_and_type_ref_i; - } + int new_klass_ref_i = find_or_append_indirect_entry(scratch_cp, klass_ref_i, + merge_cp_p, merge_cp_length_p, THREAD); + + int name_and_type_ref_i = scratch_cp->uncached_name_and_type_ref_index_at(scratch_i); + int new_name_and_type_ref_i = find_or_append_indirect_entry(scratch_cp, name_and_type_ref_i, + merge_cp_p, merge_cp_length_p, THREAD); const char *entry_name; switch (scratch_cp->tag_at(scratch_i).value()) { @@ -517,6 +371,72 @@ (*merge_cp_length_p)++; } break; + // this is an indirect CP entry so it needs special handling + case JVM_CONSTANT_MethodType: + { + int ref_i = scratch_cp->method_type_index_at(scratch_i); + int new_ref_i = find_or_append_indirect_entry(scratch_cp, ref_i, merge_cp_p, + merge_cp_length_p, THREAD); + if (new_ref_i != ref_i) { + RC_TRACE(0x00080000, + ("MethodType entry@%d ref_index change: %d to %d", + *merge_cp_length_p, ref_i, new_ref_i)); + } + (*merge_cp_p)->method_type_index_at_put(*merge_cp_length_p, new_ref_i); + if (scratch_i != *merge_cp_length_p) { + // The new entry in *merge_cp_p is at a different index than + // the new entry in scratch_cp so we need to map the index values. + map_index(scratch_cp, scratch_i, *merge_cp_length_p); + } + (*merge_cp_length_p)++; + } break; + + // this is an indirect CP entry so it needs special handling + case JVM_CONSTANT_MethodHandle: + { + int ref_kind = scratch_cp->method_handle_ref_kind_at(scratch_i); + int ref_i = scratch_cp->method_handle_index_at(scratch_i); + int new_ref_i = find_or_append_indirect_entry(scratch_cp, ref_i, merge_cp_p, + merge_cp_length_p, THREAD); + if (new_ref_i != ref_i) { + RC_TRACE(0x00080000, + ("MethodHandle entry@%d ref_index change: %d to %d", + *merge_cp_length_p, ref_i, new_ref_i)); + } + (*merge_cp_p)->method_handle_index_at_put(*merge_cp_length_p, ref_kind, new_ref_i); + if (scratch_i != *merge_cp_length_p) { + // The new entry in *merge_cp_p is at a different index than + // the new entry in scratch_cp so we need to map the index values. + map_index(scratch_cp, scratch_i, *merge_cp_length_p); + } + (*merge_cp_length_p)++; + } break; + + // this is an indirect CP entry so it needs special handling + case JVM_CONSTANT_InvokeDynamic: + { + // TBD: cross-checks and possible extra appends into CP and bsm operands + // are needed as well. This issue is tracked by a separate bug 8007037. + int bss_idx = scratch_cp->invoke_dynamic_bootstrap_specifier_index(scratch_i); + + int ref_i = scratch_cp->invoke_dynamic_name_and_type_ref_index_at(scratch_i); + int new_ref_i = find_or_append_indirect_entry(scratch_cp, ref_i, merge_cp_p, + merge_cp_length_p, THREAD); + if (new_ref_i != ref_i) { + RC_TRACE(0x00080000, + ("InvokeDynamic entry@%d name_and_type ref_index change: %d to %d", + *merge_cp_length_p, ref_i, new_ref_i)); + } + + (*merge_cp_p)->invoke_dynamic_at_put(*merge_cp_length_p, bss_idx, new_ref_i); + if (scratch_i != *merge_cp_length_p) { + // The new entry in *merge_cp_p is at a different index than + // the new entry in scratch_cp so we need to map the index values. + map_index(scratch_cp, scratch_i, *merge_cp_length_p); + } + (*merge_cp_length_p)++; + } break; + // At this stage, Class or UnresolvedClass could be here, but not // ClassIndex case JVM_CONSTANT_ClassIndex: // fall through @@ -543,24 +463,33 @@ } // end append_entry() -void VM_RedefineClasses::swap_all_method_annotations(int i, int j, instanceKlassHandle scratch_class, TRAPS) { - AnnotationArray* save; - - Annotations* sca = scratch_class->annotations(); - if (sca == NULL) return; - - save = sca->get_method_annotations_of(i); - sca->set_method_annotations_of(scratch_class, i, sca->get_method_annotations_of(j), CHECK); - sca->set_method_annotations_of(scratch_class, j, save, CHECK); - - save = sca->get_method_parameter_annotations_of(i); - sca->set_method_parameter_annotations_of(scratch_class, i, sca->get_method_parameter_annotations_of(j), CHECK); - sca->set_method_parameter_annotations_of(scratch_class, j, save, CHECK); - - save = sca->get_method_default_annotations_of(i); - sca->set_method_default_annotations_of(scratch_class, i, sca->get_method_default_annotations_of(j), CHECK); - sca->set_method_default_annotations_of(scratch_class, j, save, CHECK); -} +int VM_RedefineClasses::find_or_append_indirect_entry(constantPoolHandle scratch_cp, + int ref_i, constantPoolHandle *merge_cp_p, int *merge_cp_length_p, TRAPS) { + + int new_ref_i = ref_i; + bool match = (ref_i < *merge_cp_length_p) && + scratch_cp->compare_entry_to(ref_i, *merge_cp_p, ref_i, THREAD); + + if (!match) { + // forward reference in *merge_cp_p or not a direct match + int found_i = scratch_cp->find_matching_entry(ref_i, *merge_cp_p, THREAD); + if (found_i != 0) { + guarantee(found_i != ref_i, "compare_entry_to() and find_matching_entry() do not agree"); + // Found a matching entry somewhere else in *merge_cp_p so just need a mapping entry. + new_ref_i = found_i; + map_index(scratch_cp, ref_i, found_i); + } else { + // no match found so we have to append this entry to *merge_cp_p + append_entry(scratch_cp, ref_i, merge_cp_p, merge_cp_length_p, THREAD); + // The above call to append_entry() can only append one entry + // so the post call query of *merge_cp_length_p is only for + // the sake of consistency. + new_ref_i = *merge_cp_length_p - 1; + } + } + + return new_ref_i; +} // end find_or_append_indirect_entry() jvmtiError VM_RedefineClasses::compare_and_normalize_class_versions( @@ -744,10 +673,9 @@ idnum_owner->set_method_idnum(new_num); } k_new_method->set_method_idnum(old_num); - swap_all_method_annotations(old_num, new_num, scratch_class, thread); - if (thread->has_pending_exception()) { - return JVMTI_ERROR_OUT_OF_MEMORY; - } + if (thread->has_pending_exception()) { + return JVMTI_ERROR_OUT_OF_MEMORY; + } } } RC_TRACE(0x00008000, ("Method matched: new: %s [%d] == old: %s [%d]", @@ -780,7 +708,6 @@ idnum_owner->set_method_idnum(new_num); } k_new_method->set_method_idnum(num); - swap_all_method_annotations(new_num, num, scratch_class, thread); if (thread->has_pending_exception()) { return JVMTI_ERROR_OUT_OF_MEMORY; } @@ -1158,6 +1085,8 @@ } } // end for each old_cp entry + ConstantPool::copy_operands(old_cp, *merge_cp_p, CHECK_0); + // We don't need to sanity check that *merge_cp_length_p is within // *merge_cp_p bounds since we have the minimum on-entry check above. (*merge_cp_length_p) = old_i; @@ -1341,8 +1270,12 @@ _index_map_count = 0; _index_map_p = new intArray(scratch_cp->length(), -1); + // reference to the cp holder is needed for copy_operands() + merge_cp->set_pool_holder(scratch_class()); bool result = merge_constant_pools(old_cp, scratch_cp, &merge_cp, &merge_cp_length, THREAD); + merge_cp->set_pool_holder(NULL); + if (!result) { // The merge can fail due to memory allocation failure or due // to robustness checks. @@ -1594,6 +1527,7 @@ case Bytecodes::_getfield : // fall through case Bytecodes::_getstatic : // fall through case Bytecodes::_instanceof : // fall through + case Bytecodes::_invokedynamic : // fall through case Bytecodes::_invokeinterface: // fall through case Bytecodes::_invokespecial : // fall through case Bytecodes::_invokestatic : // fall through @@ -1615,15 +1549,27 @@ bcp, cp_index, new_index)); // Rewriter::rewrite_method() uses put_native_u2() in this // situation because it is reusing the constant pool index - // location for a native index into the constantPoolCache. + // location for a native index into the ConstantPoolCache. // Since we are updating the constant pool index prior to - // verification and constantPoolCache initialization, we + // verification and ConstantPoolCache initialization, we // need to keep the new index in Java byte order. Bytes::put_Java_u2(p, new_index); } } break; } } // end for each bytecode + + // We also need to rewrite the parameter name indexes, if there is + // method parameter data present + if(method->has_method_parameters()) { + const int len = method->method_parameters_length(); + MethodParametersElement* elem = method->method_parameters_start(); + + for (int i = 0; i < len; i++) { + const u2 cp_index = elem[i].name_cp_index; + elem[i].name_cp_index = find_new_index(cp_index); + } + } } // end rewrite_cp_refs_in_method() @@ -1939,10 +1885,7 @@ bool VM_RedefineClasses::rewrite_cp_refs_in_fields_annotations( instanceKlassHandle scratch_class, TRAPS) { - Annotations* sca = scratch_class->annotations(); - if (sca == NULL) return true; - - Array* fields_annotations = sca->fields_annotations(); + Array* fields_annotations = scratch_class->fields_annotations(); if (fields_annotations == NULL || fields_annotations->length() == 0) { // no fields_annotations so nothing to do @@ -1977,21 +1920,10 @@ bool VM_RedefineClasses::rewrite_cp_refs_in_methods_annotations( instanceKlassHandle scratch_class, TRAPS) { - Annotations* sca = scratch_class->annotations(); - if (sca == NULL) return true; - - Array* methods_annotations = sca->methods_annotations(); - - if (methods_annotations == NULL || methods_annotations->length() == 0) { - // no methods_annotations so nothing to do - return true; - } - - RC_TRACE_WITH_THREAD(0x02000000, THREAD, - ("methods_annotations length=%d", methods_annotations->length())); - - for (int i = 0; i < methods_annotations->length(); i++) { - AnnotationArray* method_annotations = methods_annotations->at(i); + for (int i = 0; i < scratch_class->methods()->length(); i++) { + Method* m = scratch_class->methods()->at(i); + AnnotationArray* method_annotations = m->constMethod()->method_annotations(); + if (method_annotations == NULL || method_annotations->length() == 0) { // this method does not have any annotations so skip it continue; @@ -2027,24 +1959,9 @@ bool VM_RedefineClasses::rewrite_cp_refs_in_methods_parameter_annotations( instanceKlassHandle scratch_class, TRAPS) { - Annotations* sca = scratch_class->annotations(); - if (sca == NULL) return true; - - Array* methods_parameter_annotations = - sca->methods_parameter_annotations(); - - if (methods_parameter_annotations == NULL - || methods_parameter_annotations->length() == 0) { - // no methods_parameter_annotations so nothing to do - return true; - } - - RC_TRACE_WITH_THREAD(0x02000000, THREAD, - ("methods_parameter_annotations length=%d", - methods_parameter_annotations->length())); - - for (int i = 0; i < methods_parameter_annotations->length(); i++) { - AnnotationArray* method_parameter_annotations = methods_parameter_annotations->at(i); + for (int i = 0; i < scratch_class->methods()->length(); i++) { + Method* m = scratch_class->methods()->at(i); + AnnotationArray* method_parameter_annotations = m->constMethod()->parameter_annotations(); if (method_parameter_annotations == NULL || method_parameter_annotations->length() == 0) { // this method does not have any parameter annotations so skip it @@ -2094,24 +2011,9 @@ bool VM_RedefineClasses::rewrite_cp_refs_in_methods_default_annotations( instanceKlassHandle scratch_class, TRAPS) { - Annotations* sca = scratch_class->annotations(); - if (sca == NULL) return true; - - Array* methods_default_annotations = - sca->methods_default_annotations(); - - if (methods_default_annotations == NULL - || methods_default_annotations->length() == 0) { - // no methods_default_annotations so nothing to do - return true; - } - - RC_TRACE_WITH_THREAD(0x02000000, THREAD, - ("methods_default_annotations length=%d", - methods_default_annotations->length())); - - for (int i = 0; i < methods_default_annotations->length(); i++) { - AnnotationArray* method_default_annotations = methods_default_annotations->at(i); + for (int i = 0; i < scratch_class->methods()->length(); i++) { + Method* m = scratch_class->methods()->at(i); + AnnotationArray* method_default_annotations = m->constMethod()->default_annotations(); if (method_default_annotations == NULL || method_default_annotations->length() == 0) { // this method does not have any default annotations so skip it @@ -2416,13 +2318,14 @@ assert(version != 0, "sanity check"); smaller_cp->set_version(version); + // attach klass to new constant pool + // reference to the cp holder is needed for copy_operands() + smaller_cp->set_pool_holder(scratch_class()); + scratch_cp->copy_cp_to(1, scratch_cp_length - 1, smaller_cp, 1, THREAD); scratch_cp = smaller_cp; // attach new constant pool to klass - scratch_cp->set_pool_holder(scratch_class()); - - // attach klass to new constant pool scratch_class->set_constants(scratch_cp()); int i; // for portability @@ -3115,6 +3018,31 @@ } +void VM_RedefineClasses::swap_annotations(instanceKlassHandle the_class, + instanceKlassHandle scratch_class) { + // Since there is currently no rewriting of type annotations indexes + // into the CP, we null out type annotations on scratch_class before + // we swap annotations with the_class rather than facing the + // possibility of shipping annotations with broken indexes to + // Java-land. + ClassLoaderData* loader_data = scratch_class->class_loader_data(); + AnnotationArray* new_class_type_annotations = scratch_class->class_type_annotations(); + if (new_class_type_annotations != NULL) { + MetadataFactory::free_array(loader_data, new_class_type_annotations); + scratch_class->annotations()->set_class_type_annotations(NULL); + } + Array* new_field_type_annotations = scratch_class->fields_type_annotations(); + if (new_field_type_annotations != NULL) { + Annotations::free_contents(loader_data, new_field_type_annotations); + scratch_class->annotations()->set_fields_type_annotations(NULL); + } + + // Swap annotation fields values + Annotations* old_annotations = the_class->annotations(); + the_class->set_annotations(scratch_class->annotations()); + scratch_class->set_annotations(old_annotations); +} + // Install the redefinition of a class: // - house keeping (flushing breakpoints and caches, deoptimizing @@ -3140,11 +3068,9 @@ Klass* the_class_oop = java_lang_Class::as_Klass(the_class_mirror); instanceKlassHandle the_class = instanceKlassHandle(THREAD, the_class_oop); -#ifndef JVMTI_KERNEL // Remove all breakpoints in methods of this class JvmtiBreakpoints& jvmti_breakpoints = JvmtiCurrentBreakpoints::get_jvmti_breakpoints(); jvmti_breakpoints.clearall_in_class_at_safepoint(the_class_oop); -#endif // !JVMTI_KERNEL if (the_class_oop == Universe::reflect_invoke_cache()->klass()) { // We are redefining java.lang.reflect.Method. Method.invoke() is @@ -3327,23 +3253,7 @@ the_class->set_access_flags(flags); } - // Since there is currently no rewriting of type annotations indexes - // into the CP, we null out type annotations on scratch_class before - // we swap annotations with the_class rather than facing the - // possibility of shipping annotations with broken indexes to - // Java-land. - Annotations* new_annotations = scratch_class->annotations(); - if (new_annotations != NULL) { - Annotations* new_type_annotations = new_annotations->type_annotations(); - if (new_type_annotations != NULL) { - MetadataFactory::free_metadata(scratch_class->class_loader_data(), new_type_annotations); - new_annotations->set_type_annotations(NULL); - } - } - // Swap annotation fields values - Annotations* old_annotations = the_class->annotations(); - the_class->set_annotations(scratch_class->annotations()); - scratch_class->set_annotations(old_annotations); + swap_annotations(the_class, scratch_class); // Replace minor version number of class file u2 old_minor_version = the_class->minor_version(); @@ -3423,7 +3333,6 @@ } } -#ifndef PRODUCT void VM_RedefineClasses::check_class(Klass* k_oop, ClassLoaderData* initiating_loader, TRAPS) { @@ -3431,82 +3340,110 @@ if (k->oop_is_instance()) { HandleMark hm(THREAD); InstanceKlass *ik = (InstanceKlass *) k; - - if (ik->vtable_length() > 0) { - ResourceMark rm(THREAD); - if (!ik->vtable()->check_no_old_entries()) { - tty->print_cr("klassVtable::check_no_old_entries failure -- OLD method found -- class: %s", ik->signature_name()); + bool no_old_methods = true; // be optimistic + ResourceMark rm(THREAD); + + // a vtable should never contain old or obsolete methods + if (ik->vtable_length() > 0 && + !ik->vtable()->check_no_old_or_obsolete_entries()) { + if (RC_TRACE_ENABLED(0x00004000)) { + RC_TRACE_WITH_THREAD(0x00004000, THREAD, + ("klassVtable::check_no_old_or_obsolete_entries failure" + " -- OLD or OBSOLETE method found -- class: %s", + ik->signature_name())); ik->vtable()->dump_vtable(); - assert(false, "OLD method found"); } + no_old_methods = false; } - if (ik->itable_length() > 0) { - ResourceMark rm(THREAD); - if (!ik->itable()->check_no_old_entries()) { - tty->print_cr("klassItable::check_no_old_entries failure -- OLD method found -- class: %s", ik->signature_name()); - assert(false, "OLD method found"); + + // an itable should never contain old or obsolete methods + if (ik->itable_length() > 0 && + !ik->itable()->check_no_old_or_obsolete_entries()) { + if (RC_TRACE_ENABLED(0x00004000)) { + RC_TRACE_WITH_THREAD(0x00004000, THREAD, + ("klassItable::check_no_old_or_obsolete_entries failure" + " -- OLD or OBSOLETE method found -- class: %s", + ik->signature_name())); + ik->itable()->dump_itable(); } + no_old_methods = false; } - // Check that the constant pool cache has no deleted entries. + + // the constant pool cache should never contain old or obsolete methods if (ik->constants() != NULL && ik->constants()->cache() != NULL && - !ik->constants()->cache()->check_no_old_entries()) { - tty->print_cr("klassVtable::check_no_old_entries failure -- OLD method found -- class: %s", ik->signature_name()); - assert(false, "OLD method found"); + !ik->constants()->cache()->check_no_old_or_obsolete_entries()) { + if (RC_TRACE_ENABLED(0x00004000)) { + RC_TRACE_WITH_THREAD(0x00004000, THREAD, + ("cp-cache::check_no_old_or_obsolete_entries failure" + " -- OLD or OBSOLETE method found -- class: %s", + ik->signature_name())); + ik->constants()->cache()->dump_cache(); + } + no_old_methods = false; + } + + if (!no_old_methods) { + if (RC_TRACE_ENABLED(0x00004000)) { + dump_methods(); + } else { + tty->print_cr("INFO: use the '-XX:TraceRedefineClasses=16384' option " + "to see more info about the following guarantee() failure."); + } + guarantee(false, "OLD and/or OBSOLETE method(s) found"); } } } void VM_RedefineClasses::dump_methods() { - int j; - tty->print_cr("_old_methods --"); - for (j = 0; j < _old_methods->length(); ++j) { - Method* m = _old_methods->at(j); - tty->print("%4d (%5d) ", j, m->vtable_index()); - m->access_flags().print_on(tty); - tty->print(" -- "); - m->print_name(tty); - tty->cr(); - } - tty->print_cr("_new_methods --"); - for (j = 0; j < _new_methods->length(); ++j) { - Method* m = _new_methods->at(j); - tty->print("%4d (%5d) ", j, m->vtable_index()); - m->access_flags().print_on(tty); - tty->print(" -- "); - m->print_name(tty); - tty->cr(); - } - tty->print_cr("_matching_(old/new)_methods --"); - for (j = 0; j < _matching_methods_length; ++j) { - Method* m = _matching_old_methods[j]; - tty->print("%4d (%5d) ", j, m->vtable_index()); - m->access_flags().print_on(tty); - tty->print(" -- "); - m->print_name(tty); - tty->cr(); - m = _matching_new_methods[j]; - tty->print(" (%5d) ", m->vtable_index()); - m->access_flags().print_on(tty); - tty->cr(); - } - tty->print_cr("_deleted_methods --"); - for (j = 0; j < _deleted_methods_length; ++j) { - Method* m = _deleted_methods[j]; - tty->print("%4d (%5d) ", j, m->vtable_index()); - m->access_flags().print_on(tty); - tty->print(" -- "); - m->print_name(tty); - tty->cr(); - } - tty->print_cr("_added_methods --"); - for (j = 0; j < _added_methods_length; ++j) { - Method* m = _added_methods[j]; - tty->print("%4d (%5d) ", j, m->vtable_index()); - m->access_flags().print_on(tty); - tty->print(" -- "); - m->print_name(tty); - tty->cr(); - } + int j; + RC_TRACE(0x00004000, ("_old_methods --")); + for (j = 0; j < _old_methods->length(); ++j) { + Method* m = _old_methods->at(j); + RC_TRACE_NO_CR(0x00004000, ("%4d (%5d) ", j, m->vtable_index())); + m->access_flags().print_on(tty); + tty->print(" -- "); + m->print_name(tty); + tty->cr(); + } + RC_TRACE(0x00004000, ("_new_methods --")); + for (j = 0; j < _new_methods->length(); ++j) { + Method* m = _new_methods->at(j); + RC_TRACE_NO_CR(0x00004000, ("%4d (%5d) ", j, m->vtable_index())); + m->access_flags().print_on(tty); + tty->print(" -- "); + m->print_name(tty); + tty->cr(); + } + RC_TRACE(0x00004000, ("_matching_(old/new)_methods --")); + for (j = 0; j < _matching_methods_length; ++j) { + Method* m = _matching_old_methods[j]; + RC_TRACE_NO_CR(0x00004000, ("%4d (%5d) ", j, m->vtable_index())); + m->access_flags().print_on(tty); + tty->print(" -- "); + m->print_name(tty); + tty->cr(); + m = _matching_new_methods[j]; + RC_TRACE_NO_CR(0x00004000, (" (%5d) ", m->vtable_index())); + m->access_flags().print_on(tty); + tty->cr(); + } + RC_TRACE(0x00004000, ("_deleted_methods --")); + for (j = 0; j < _deleted_methods_length; ++j) { + Method* m = _deleted_methods[j]; + RC_TRACE_NO_CR(0x00004000, ("%4d (%5d) ", j, m->vtable_index())); + m->access_flags().print_on(tty); + tty->print(" -- "); + m->print_name(tty); + tty->cr(); + } + RC_TRACE(0x00004000, ("_added_methods --")); + for (j = 0; j < _added_methods_length; ++j) { + Method* m = _added_methods[j]; + RC_TRACE_NO_CR(0x00004000, ("%4d (%5d) ", j, m->vtable_index())); + m->access_flags().print_on(tty); + tty->print(" -- "); + m->print_name(tty); + tty->cr(); + } } -#endif diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/prims/jvmtiRedefineClasses.hpp --- a/src/share/vm/prims/jvmtiRedefineClasses.hpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/prims/jvmtiRedefineClasses.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -384,11 +384,6 @@ jvmtiError compare_and_normalize_class_versions( instanceKlassHandle the_class, instanceKlassHandle scratch_class); - // Swap annotations[i] with annotations[j] - // Used by compare_and_normalize_class_versions() when normalizing - // overloaded methods or changing idnum as when adding or deleting methods. - void swap_all_method_annotations(int i, int j, instanceKlassHandle scratch_class, TRAPS); - // Figure out which new methods match old methods in name and signature, // which methods have been added, and which are no longer present void compute_added_deleted_matching_methods(); @@ -417,14 +412,18 @@ void redefine_single_class(jclass the_jclass, Klass* scratch_class_oop, TRAPS); + void swap_annotations(instanceKlassHandle new_class, + instanceKlassHandle scratch_class); + // Increment the classRedefinedCount field in the specific InstanceKlass // and in all direct and indirect subclasses. void increment_class_counter(InstanceKlass *ik, TRAPS); - // Support for constant pool merging (these routines are in alpha - // order): + // Support for constant pool merging (these routines are in alpha order): void append_entry(constantPoolHandle scratch_cp, int scratch_i, constantPoolHandle *merge_cp_p, int *merge_cp_length_p, TRAPS); + int find_or_append_indirect_entry(constantPoolHandle scratch_cp, int scratch_i, + constantPoolHandle *merge_cp_p, int *merge_cp_length_p, TRAPS); int find_new_index(int old_index); bool is_unresolved_class_mismatch(constantPoolHandle cp1, int index1, constantPoolHandle cp2, int index2); @@ -467,9 +466,9 @@ void flush_dependent_code(instanceKlassHandle k_h, TRAPS); - static void check_class(Klass* k_oop, ClassLoaderData* initiating_loader, TRAPS) PRODUCT_RETURN; - - static void dump_methods() PRODUCT_RETURN; + static void check_class(Klass* k_oop, ClassLoaderData* initiating_loader, + TRAPS); + static void dump_methods(); public: VM_RedefineClasses(jint class_count, @@ -487,17 +486,4 @@ // and redefine implementation static bool is_modifiable_class(oop klass_mirror); }; - - -// Helper class to mark and unmark metadata used on the stack as either handles -// or executing methods, so that it can't be deleted during class redefinition -// and class unloading. -class MetadataOnStackMark : public StackObj { - NOT_PRODUCT(static bool _is_active;) - public: - MetadataOnStackMark() NOT_JVMTI_RETURN; - ~MetadataOnStackMark() NOT_JVMTI_RETURN; - static void record(Metadata* m) NOT_JVMTI_RETURN; -}; - #endif // SHARE_VM_PRIMS_JVMTIREDEFINECLASSES_HPP diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/prims/jvmtiRedefineClassesTrace.hpp --- a/src/share/vm/prims/jvmtiRedefineClassesTrace.hpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/prims/jvmtiRedefineClassesTrace.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -54,7 +54,7 @@ // 0x00000800 | 2048 - previous class breakpoint mgmt // 0x00001000 | 4096 - detect calls to obsolete methods // 0x00002000 | 8192 - fail a guarantee() in addition to detection -// 0x00004000 | 16384 - unused +// 0x00004000 | 16384 - detect old/obsolete methods in metadata // 0x00008000 | 32768 - old/new method matching/add/delete // 0x00010000 | 65536 - impl details: CP size info // 0x00020000 | 131072 - impl details: CP merge pass info @@ -82,6 +82,13 @@ tty->print_cr args; \ } while (0) +#define RC_TRACE_NO_CR(level, args) \ + if ((TraceRedefineClasses & level) != 0) { \ + ResourceMark rm; \ + tty->print("RedefineClasses-0x%x: ", level); \ + tty->print args; \ + } while (0) + #define RC_TRACE_WITH_THREAD(level, thread, args) \ if ((TraceRedefineClasses & level) != 0) { \ ResourceMark rm(thread); \ diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/prims/jvmtiTagMap.cpp --- a/src/share/vm/prims/jvmtiTagMap.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/prims/jvmtiTagMap.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -45,9 +45,10 @@ #include "runtime/vmThread.hpp" #include "runtime/vm_operations.hpp" #include "services/serviceUtil.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/parallelScavenge/parallelScavengeHeap.hpp" -#endif +#endif // INCLUDE_ALL_GCS // JvmtiTagHashmapEntry // diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/prims/jvmtiTagMap.hpp --- a/src/share/vm/prims/jvmtiTagMap.hpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/prims/jvmtiTagMap.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,14 +27,12 @@ #ifndef SHARE_VM_PRIMS_JVMTITAGMAP_HPP #define SHARE_VM_PRIMS_JVMTITAGMAP_HPP -#ifndef JVMTI_KERNEL #include "gc_interface/collectedHeap.hpp" #include "jvmtifiles/jvmti.h" #include "jvmtifiles/jvmtiEnv.hpp" #include "memory/allocation.hpp" #include "memory/genCollectedHeap.hpp" #include "memory/universe.hpp" -#endif // forward references class JvmtiTagHashmap; diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/prims/nativeLookup.cpp --- a/src/share/vm/prims/nativeLookup.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/prims/nativeLookup.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -40,6 +40,7 @@ #include "runtime/javaCalls.hpp" #include "runtime/sharedRuntime.hpp" #include "runtime/signature.hpp" +#include "utilities/macros.hpp" #ifdef TARGET_OS_FAMILY_linux # include "os_linux.inline.hpp" #endif diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/prims/unsafe.cpp --- a/src/share/vm/prims/unsafe.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/prims/unsafe.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -24,9 +24,10 @@ #include "precompiled.hpp" #include "classfile/vmSymbols.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp" -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS #include "memory/allocation.inline.hpp" #include "prims/jni.h" #include "prims/jvm.h" @@ -189,7 +190,7 @@ if (obj == NULL) THROW_0(vmSymbols::java_lang_NullPointerException()); GET_OOP_FIELD(obj, offset, v) jobject ret = JNIHandles::make_local(env, v); -#ifndef SERIALGC +#if INCLUDE_ALL_GCS // We could be accessing the referent field in a reference // object. If G1 is enabled then we need to register a non-null // referent with the SATB barrier. @@ -212,7 +213,7 @@ G1SATBCardTableModRefBS::enqueue(referent); } } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS return ret; UNSAFE_END @@ -247,7 +248,7 @@ UnsafeWrapper("Unsafe_GetObject"); GET_OOP_FIELD(obj, offset, v) jobject ret = JNIHandles::make_local(env, v); -#ifndef SERIALGC +#if INCLUDE_ALL_GCS // We could be accessing the referent field in a reference // object. If G1 is enabled then we need to register non-null // referent with the SATB barrier. @@ -270,7 +271,7 @@ G1SATBCardTableModRefBS::enqueue(referent); } } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS return ret; UNSAFE_END diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/prims/wbtestmethods/parserTests.hpp --- a/src/share/vm/prims/wbtestmethods/parserTests.hpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/prims/wbtestmethods/parserTests.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -27,6 +27,6 @@ #include "prims/jni.h" #include "prims/whitebox.hpp" -WB_METHOD_DECLARE WB_ParseCommandLine(JNIEnv* env, jobject o, jstring args, jobjectArray arguments); +WB_METHOD_DECLARE(jobjectArray) WB_ParseCommandLine(JNIEnv* env, jobject o, jstring args, jobjectArray arguments); #endif //SHARE_VM_PRIMS_WBTESTMETHODS_PARSERTESTS_H diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/prims/whitebox.cpp --- a/src/share/vm/prims/whitebox.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/prims/whitebox.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -36,12 +36,19 @@ #include "runtime/interfaceSupport.hpp" #include "runtime/os.hpp" #include "utilities/debug.hpp" +#include "utilities/macros.hpp" -#ifndef SERIALGC +#if INCLUDE_ALL_GCS #include "gc_implementation/g1/concurrentMark.hpp" #include "gc_implementation/g1/g1CollectedHeap.inline.hpp" #include "gc_implementation/g1/heapRegionRemSet.hpp" -#endif // !SERIALGC +#endif // INCLUDE_ALL_GCS + +#ifdef INCLUDE_NMT +#include "services/memTracker.hpp" +#endif // INCLUDE_NMT + +#include "compiler/compileBroker.hpp" bool WhiteBox::_used = false; @@ -85,7 +92,7 @@ return closure.found(); WB_END -#ifndef SERIALGC +#if INCLUDE_ALL_GCS WB_ENTRY(jboolean, WB_G1IsHumongous(JNIEnv* env, jobject o, jobject obj)) G1CollectedHeap* g1 = G1CollectedHeap::heap(); oop result = JNIHandles::resolve(obj); @@ -108,7 +115,144 @@ WB_ENTRY(jint, WB_G1RegionSize(JNIEnv* env, jobject o)) return (jint)HeapRegion::GrainBytes; WB_END -#endif // !SERIALGC +#endif // INCLUDE_ALL_GCS + +#ifdef INCLUDE_NMT +// Keep track of the 3 allocations in NMTAllocTest so we can free them later +// on and verify that they're not visible anymore +static void* nmtMtTest1 = NULL, *nmtMtTest2 = NULL, *nmtMtTest3 = NULL; + +// Alloc memory using the test memory type so that we can use that to see if +// NMT picks it up correctly +WB_ENTRY(jboolean, WB_NMTAllocTest(JNIEnv* env)) + void *mem; + + if (!MemTracker::is_on() || MemTracker::shutdown_in_progress()) { + return false; + } + + // Allocate 2 * 128k + 256k + 1024k and free the 1024k one to make sure we track + // everything correctly. Total should be 512k held alive. + nmtMtTest1 = os::malloc(128 * 1024, mtTest); + mem = os::malloc(1024 * 1024, mtTest); + nmtMtTest2 = os::malloc(256 * 1024, mtTest); + os::free(mem, mtTest); + nmtMtTest3 = os::malloc(128 * 1024, mtTest); + + return true; +WB_END + +// Free the memory allocated by NMTAllocTest +WB_ENTRY(jboolean, WB_NMTFreeTestMemory(JNIEnv* env)) + + if (nmtMtTest1 == NULL || nmtMtTest2 == NULL || nmtMtTest3 == NULL) { + return false; + } + + os::free(nmtMtTest1, mtTest); + nmtMtTest1 = NULL; + os::free(nmtMtTest2, mtTest); + nmtMtTest2 = NULL; + os::free(nmtMtTest3, mtTest); + nmtMtTest3 = NULL; + + return true; +WB_END + +// Block until the current generation of NMT data to be merged, used to reliably test the NMT feature +WB_ENTRY(jboolean, WB_NMTWaitForDataMerge(JNIEnv* env)) + + if (!MemTracker::is_on() || MemTracker::shutdown_in_progress()) { + return false; + } + + return MemTracker::wbtest_wait_for_data_merge(); +WB_END + +#endif // INCLUDE_NMT + +static jmethodID reflected_method_to_jmid(JavaThread* thread, JNIEnv* env, jobject method) { + assert(method != NULL, "method should not be null"); + ThreadToNativeFromVM ttn(thread); + return env->FromReflectedMethod(method); +} + +WB_ENTRY(void, WB_DeoptimizeAll(JNIEnv* env, jobject o)) + MutexLockerEx mu(Compile_lock); + CodeCache::mark_all_nmethods_for_deoptimization(); + VM_Deoptimize op; + VMThread::execute(&op); +WB_END + +WB_ENTRY(jint, WB_DeoptimizeMethod(JNIEnv* env, jobject o, jobject method)) + jmethodID jmid = reflected_method_to_jmid(thread, env, method); + MutexLockerEx mu(Compile_lock); + methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid)); + int result = 0; + nmethod* code = mh->code(); + if (code != NULL) { + code->mark_for_deoptimization(); + ++result; + } + result += CodeCache::mark_for_deoptimization(mh()); + if (result > 0) { + VM_Deoptimize op; + VMThread::execute(&op); + } + return result; +WB_END + +WB_ENTRY(jboolean, WB_IsMethodCompiled(JNIEnv* env, jobject o, jobject method)) + jmethodID jmid = reflected_method_to_jmid(thread, env, method); + MutexLockerEx mu(Compile_lock); + methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid)); + nmethod* code = mh->code(); + if (code == NULL) { + return JNI_FALSE; + } + return (code->is_alive() && !code->is_marked_for_deoptimization()); +WB_END + +WB_ENTRY(jboolean, WB_IsMethodCompilable(JNIEnv* env, jobject o, jobject method)) + jmethodID jmid = reflected_method_to_jmid(thread, env, method); + MutexLockerEx mu(Compile_lock); + methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid)); + return !mh->is_not_compilable(); +WB_END + +WB_ENTRY(jboolean, WB_IsMethodQueuedForCompilation(JNIEnv* env, jobject o, jobject method)) + jmethodID jmid = reflected_method_to_jmid(thread, env, method); + MutexLockerEx mu(Compile_lock); + methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid)); + return mh->queued_for_compilation(); +WB_END + +WB_ENTRY(jint, WB_GetMethodCompilationLevel(JNIEnv* env, jobject o, jobject method)) + jmethodID jmid = reflected_method_to_jmid(thread, env, method); + methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid)); + nmethod* code = mh->code(); + return (code != NULL ? code->comp_level() : CompLevel_none); +WB_END + + +WB_ENTRY(void, WB_MakeMethodNotCompilable(JNIEnv* env, jobject o, jobject method)) + jmethodID jmid = reflected_method_to_jmid(thread, env, method); + methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid)); + mh->set_not_compilable(); +WB_END + +WB_ENTRY(jboolean, WB_SetDontInlineMethod(JNIEnv* env, jobject o, jobject method, jboolean value)) + jmethodID jmid = reflected_method_to_jmid(thread, env, method); + methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid)); + bool result = mh->dont_inline(); + mh->set_dont_inline(value == JNI_TRUE); + return result; +WB_END + +WB_ENTRY(jint, WB_GetCompileQueuesSize(JNIEnv* env, jobject o)) + return CompileBroker::queue_size(CompLevel_full_optimization) /* C2 */ + + CompileBroker::queue_size(CompLevel_full_profile) /* C1 */; +WB_END //Some convenience methods to deal with objects from java int WhiteBox::offset_for_field(const char* field_name, oop object, @@ -166,17 +310,39 @@ static JNINativeMethod methods[] = { {CC"getObjectAddress", CC"(Ljava/lang/Object;)J", (void*)&WB_GetObjectAddress }, {CC"getHeapOopSize", CC"()I", (void*)&WB_GetHeapOopSize }, - {CC"isClassAlive0", CC"(Ljava/lang/String;)Z", (void*)&WB_IsClassAlive }, - {CC "parseCommandLine", - CC "(Ljava/lang/String;[Lsun/hotspot/parser/DiagnosticCommand;)[Ljava/lang/Object;", + {CC"isClassAlive0", CC"(Ljava/lang/String;)Z", (void*)&WB_IsClassAlive }, + {CC"parseCommandLine", + CC"(Ljava/lang/String;[Lsun/hotspot/parser/DiagnosticCommand;)[Ljava/lang/Object;", (void*) &WB_ParseCommandLine }, -#ifndef SERIALGC +#if INCLUDE_ALL_GCS {CC"g1InConcurrentMark", CC"()Z", (void*)&WB_G1InConcurrentMark}, {CC"g1IsHumongous", CC"(Ljava/lang/Object;)Z", (void*)&WB_G1IsHumongous }, {CC"g1NumFreeRegions", CC"()J", (void*)&WB_G1NumFreeRegions }, {CC"g1RegionSize", CC"()I", (void*)&WB_G1RegionSize }, -#endif // !SERIALGC +#endif // INCLUDE_ALL_GCS +#ifdef INCLUDE_NMT + {CC"NMTAllocTest", CC"()Z", (void*)&WB_NMTAllocTest }, + {CC"NMTFreeTestMemory", CC"()Z", (void*)&WB_NMTFreeTestMemory }, + {CC"NMTWaitForDataMerge",CC"()Z", (void*)&WB_NMTWaitForDataMerge}, +#endif // INCLUDE_NMT + {CC"deoptimizeAll", CC"()V", (void*)&WB_DeoptimizeAll }, + {CC"deoptimizeMethod", CC"(Ljava/lang/reflect/Method;)I", + (void*)&WB_DeoptimizeMethod }, + {CC"isMethodCompiled", CC"(Ljava/lang/reflect/Method;)Z", + (void*)&WB_IsMethodCompiled }, + {CC"isMethodCompilable", CC"(Ljava/lang/reflect/Method;)Z", + (void*)&WB_IsMethodCompilable}, + {CC"isMethodQueuedForCompilation", + CC"(Ljava/lang/reflect/Method;)Z", (void*)&WB_IsMethodQueuedForCompilation}, + {CC"makeMethodNotCompilable", + CC"(Ljava/lang/reflect/Method;)V", (void*)&WB_MakeMethodNotCompilable}, + {CC"setDontInlineMethod", + CC"(Ljava/lang/reflect/Method;Z)Z", (void*)&WB_SetDontInlineMethod}, + {CC"getMethodCompilationLevel", + CC"(Ljava/lang/reflect/Method;)I", (void*)&WB_GetMethodCompilationLevel}, + {CC"getCompileQueuesSize", + CC"()I", (void*)&WB_GetCompileQueuesSize}, }; #undef CC diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/prims/whitebox.hpp --- a/src/share/vm/prims/whitebox.hpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/prims/whitebox.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -34,7 +34,7 @@ #define WB_ENTRY(result_type, header) JNI_ENTRY(result_type, header) #define WB_END JNI_END -#define WB_METHOD_DECLARE extern "C" jobjectArray JNICALL +#define WB_METHOD_DECLARE(result_type) extern "C" result_type JNICALL class WhiteBox : public AllStatic { private: diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/runtime/arguments.cpp --- a/src/share/vm/runtime/arguments.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/runtime/arguments.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -38,6 +38,7 @@ #include "services/management.hpp" #include "services/memTracker.hpp" #include "utilities/defaultStream.hpp" +#include "utilities/macros.hpp" #include "utilities/taskqueue.hpp" #ifdef TARGET_OS_FAMILY_linux # include "os_linux.inline.hpp" @@ -51,9 +52,9 @@ #ifdef TARGET_OS_FAMILY_bsd # include "os_bsd.inline.hpp" #endif -#ifndef SERIALGC +#if INCLUDE_ALL_GCS #include "gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp" -#endif +#endif // INCLUDE_ALL_GCS // Note: This is a special bug reporting site for the JVM #define DEFAULT_VENDOR_URL_BUG "http://bugreport.sun.com/bugreport/crash.jsp" @@ -845,7 +846,8 @@ return true; } - const char * const argname = *arg == '+' || *arg == '-' ? arg + 1 : arg; + bool has_plus_minus = (*arg == '+' || *arg == '-'); + const char* const argname = has_plus_minus ? arg + 1 : arg; if (is_newly_obsolete(arg, &since)) { char version[256]; since.to_string(version, sizeof(version)); @@ -856,13 +858,29 @@ // For locked flags, report a custom error message if available. // Otherwise, report the standard unrecognized VM option. - Flag* locked_flag = Flag::find_flag((char*)argname, strlen(argname), true); - if (locked_flag != NULL) { + size_t arg_len; + const char* equal_sign = strchr(argname, '='); + if (equal_sign == NULL) { + arg_len = strlen(argname); + } else { + arg_len = equal_sign - argname; + } + + Flag* found_flag = Flag::find_flag((char*)argname, arg_len, true); + if (found_flag != NULL) { char locked_message_buf[BUFLEN]; - locked_flag->get_locked_message(locked_message_buf, BUFLEN); + found_flag->get_locked_message(locked_message_buf, BUFLEN); if (strlen(locked_message_buf) == 0) { - jio_fprintf(defaultStream::error_stream(), - "Unrecognized VM option '%s'\n", argname); + if (found_flag->is_bool() && !has_plus_minus) { + jio_fprintf(defaultStream::error_stream(), + "Missing +/- setting for VM option '%s'\n", argname); + } else if (!found_flag->is_bool() && has_plus_minus) { + jio_fprintf(defaultStream::error_stream(), + "Unexpected +/- setting in VM option '%s'\n", argname); + } else { + jio_fprintf(defaultStream::error_stream(), + "Improperly specified VM option '%s'\n", argname); + } } else { jio_fprintf(defaultStream::error_stream(), "%s", locked_message_buf); } @@ -1086,11 +1104,11 @@ } // Increase the code cache size - tiered compiles a lot more. if (FLAG_IS_DEFAULT(ReservedCodeCacheSize)) { - FLAG_SET_DEFAULT(ReservedCodeCacheSize, ReservedCodeCacheSize * 2); + FLAG_SET_DEFAULT(ReservedCodeCacheSize, ReservedCodeCacheSize * 5); } } -#if INCLUDE_ALTERNATE_GCS +#if INCLUDE_ALL_GCS static void disable_adaptive_size_policy(const char* collector_name) { if (UseAdaptiveSizePolicy) { if (FLAG_IS_CMDLINE(UseAdaptiveSizePolicy)) { @@ -1257,7 +1275,7 @@ // prefer minuscule survivor spaces so as not to waste // space for (non-existent) survivors if (FLAG_IS_DEFAULT(SurvivorRatio) && MaxTenuringThreshold == 0) { - FLAG_SET_ERGO(intx, SurvivorRatio, MAX2((intx)1024, SurvivorRatio)); + FLAG_SET_ERGO(uintx, SurvivorRatio, MAX2((uintx)1024, SurvivorRatio)); } // If OldPLABSize is set and CMSParPromoteBlocksToClaim is not, // set CMSParPromoteBlocksToClaim equal to OldPLABSize. @@ -1302,7 +1320,7 @@ tty->print_cr("ConcGCThreads: %u", ConcGCThreads); } } -#endif // INCLUDE_ALTERNATE_GCS +#endif // INCLUDE_ALL_GCS void set_object_alignment() { // Object alignment. @@ -1319,10 +1337,10 @@ // Oop encoding heap max OopEncodingHeapMax = (uint64_t(max_juint) + 1) << LogMinObjAlignmentInBytes; -#if INCLUDE_ALTERNATE_GCS +#if INCLUDE_ALL_GCS // Set CMS global values CompactibleFreeListSpace::set_cms_values(); -#endif // INCLUDE_ALTERNATE_GCS +#endif // INCLUDE_ALL_GCS } bool verify_object_alignment() { @@ -1447,13 +1465,18 @@ } // Set the ClassMetaspaceSize to something that will not need to be // expanded, since it cannot be expanded. - if (UseCompressedKlassPointers && FLAG_IS_DEFAULT(ClassMetaspaceSize)) { - // 100,000 classes seems like a good size, so 100M assumes around 1K - // per klass. The vtable and oopMap is embedded so we don't have a fixed - // size per klass. Eventually, this will be parameterized because it - // would also be useful to determine the optimal size of the - // systemDictionary. - FLAG_SET_ERGO(uintx, ClassMetaspaceSize, 100*M); + if (UseCompressedKlassPointers) { + if (ClassMetaspaceSize > KlassEncodingMetaspaceMax) { + warning("Class metaspace size is too large for UseCompressedKlassPointers"); + FLAG_SET_DEFAULT(UseCompressedKlassPointers, false); + } else if (FLAG_IS_DEFAULT(ClassMetaspaceSize)) { + // 100,000 classes seems like a good size, so 100M assumes around 1K + // per klass. The vtable and oopMap is embedded so we don't have a fixed + // size per klass. Eventually, this will be parameterized because it + // would also be useful to determine the optimal size of the + // systemDictionary. + FLAG_SET_ERGO(uintx, ClassMetaspaceSize, 100*M); + } } } // Also checks that certain machines are slower with compressed oops @@ -1733,16 +1756,6 @@ return false; } -static void force_serial_gc() { - FLAG_SET_DEFAULT(UseSerialGC, true); - FLAG_SET_DEFAULT(UseParNewGC, false); - FLAG_SET_DEFAULT(UseConcMarkSweepGC, false); - FLAG_SET_DEFAULT(CMSIncrementalMode, false); // special CMS suboption - FLAG_SET_DEFAULT(UseParallelGC, false); - FLAG_SET_DEFAULT(UseParallelOldGC, false); - FLAG_SET_DEFAULT(UseG1GC, false); -} - static bool verify_serial_gc_flags() { return (UseSerialGC && !(UseParNewGC || (UseConcMarkSweepGC || CMSIncrementalMode) || UseG1GC || @@ -1892,6 +1905,24 @@ // Keeping the heap 100% free is hard ;-) so limit it to 99%. MinHeapFreeRatio = MIN2(MinHeapFreeRatio, (uintx) 99); + // Min/MaxMetaspaceFreeRatio + status = status && verify_percentage(MinMetaspaceFreeRatio, "MinMetaspaceFreeRatio"); + status = status && verify_percentage(MaxMetaspaceFreeRatio, "MaxMetaspaceFreeRatio"); + + if (MinMetaspaceFreeRatio > MaxMetaspaceFreeRatio) { + jio_fprintf(defaultStream::error_stream(), + "MinMetaspaceFreeRatio (%s" UINTX_FORMAT ") must be less than or " + "equal to MaxMetaspaceFreeRatio (%s" UINTX_FORMAT ")\n", + FLAG_IS_DEFAULT(MinMetaspaceFreeRatio) ? "Default: " : "", + MinMetaspaceFreeRatio, + FLAG_IS_DEFAULT(MaxMetaspaceFreeRatio) ? "Default: " : "", + MaxMetaspaceFreeRatio); + status = false; + } + + // Trying to keep 100% free is not practical + MinMetaspaceFreeRatio = MIN2(MinMetaspaceFreeRatio, (uintx) 99); + if (FullGCALot && FLAG_IS_DEFAULT(MarkSweepAlwaysCompactCount)) { MarkSweepAlwaysCompactCount = 1; // Move objects every gc. } @@ -1899,7 +1930,7 @@ if (UseParallelOldGC && ParallelOldGCSplitALot) { // Settings to encourage splitting. if (!FLAG_IS_CMDLINE(NewRatio)) { - FLAG_SET_CMDLINE(intx, NewRatio, 2); + FLAG_SET_CMDLINE(uintx, NewRatio, 2); } if (!FLAG_IS_CMDLINE(ScavengeBeforeFullGC)) { FLAG_SET_CMDLINE(bool, ScavengeBeforeFullGC, false); @@ -1994,7 +2025,7 @@ status = status && verify_min_value(ParGCArrayScanChunk, 1, "ParGCArrayScanChunk"); -#ifndef SERIALGC +#if INCLUDE_ALL_GCS if (UseG1GC) { status = status && verify_percentage(InitiatingHeapOccupancyPercent, "InitiatingHeapOccupancyPercent"); @@ -2003,7 +2034,7 @@ status = status && verify_min_value((intx)G1ConcMarkStepDurationMillis, 1, "G1ConcMarkStepDurationMillis"); } -#endif +#endif // INCLUDE_ALL_GCS status = status && verify_interval(RefDiscoveryPolicy, ReferenceProcessor::DiscoveryPolicyMin, @@ -2318,19 +2349,6 @@ FREE_C_HEAP_ARRAY(char, altclasses_path, mtInternal); } - if (WhiteBoxAPI) { - // Append wb.jar to bootclasspath if enabled - const char* wb_jar = "wb.jar"; - size_t wb_path_len = strlen(get_meta_index_dir()) + 1 + - strlen(wb_jar); - char* wb_path = NEW_C_HEAP_ARRAY(char, wb_path_len, mtInternal); - strcpy(wb_path, get_meta_index_dir()); - strcat(wb_path, wb_jar); - scp.add_suffix(wb_path); - scp_assembly_required = true; - FREE_C_HEAP_ARRAY(char, wb_path, mtInternal); - } - // Parse _JAVA_OPTIONS environment variable (if present) (mimics classic VM) result = parse_java_options_environment_variable(&scp, &scp_assembly_required); if (result != JNI_OK) { @@ -2625,7 +2643,12 @@ } // Out of the box management support if (match_option(option, "-Dcom.sun.management", &tail)) { +#if INCLUDE_MANAGEMENT FLAG_SET_CMDLINE(bool, ManagementServer, true); +#else + vm_exit_during_initialization( + "-Dcom.sun.management is not supported in this VM.", NULL); +#endif } // -Xint } else if (match_option(option, "-Xint", &tail)) { @@ -2640,10 +2663,7 @@ // -Xshare:dump } else if (match_option(option, "-Xshare:dump", &tail)) { -#if defined(KERNEL) - vm_exit_during_initialization( - "Dumping a shared archive is not supported on the Kernel JVM.", NULL); -#elif !INCLUDE_CDS +#if !INCLUDE_CDS vm_exit_during_initialization( "Dumping a shared archive is not supported in this VM.", NULL); #else @@ -2974,6 +2994,11 @@ // away and will cause VM initialization failures! warning("-XX:+UseVMInterruptibleIO is obsolete and will be removed in a future release."); FLAG_SET_CMDLINE(bool, UseVMInterruptibleIO, true); +#if !INCLUDE_MANAGEMENT + } else if (match_option(option, "-XX:+ManagementServer", &tail)) { + vm_exit_during_initialization( + "ManagementServer is not supported in this VM.", NULL); +#endif // INCLUDE_MANAGEMENT } else if (match_option(option, "-XX:", &tail)) { // -XX:xxxx // Skip -XX:Flags= since that case has already been handled if (strncmp(tail, "Flags=", strlen("Flags=")) != 0) { @@ -3213,6 +3238,27 @@ } \ } while(0) + +#define UNSUPPORTED_GC_OPTION(gc) \ +do { \ + if (gc) { \ + if (FLAG_IS_CMDLINE(gc)) { \ + warning(#gc " is not supported in this VM. Using Serial GC."); \ + } \ + FLAG_SET_DEFAULT(gc, false); \ + } \ +} while(0) + +static void force_serial_gc() { + FLAG_SET_DEFAULT(UseSerialGC, true); + FLAG_SET_DEFAULT(CMSIncrementalMode, false); // special CMS suboption + UNSUPPORTED_GC_OPTION(UseG1GC); + UNSUPPORTED_GC_OPTION(UseParallelGC); + UNSUPPORTED_GC_OPTION(UseParallelOldGC); + UNSUPPORTED_GC_OPTION(UseConcMarkSweepGC); + UNSUPPORTED_GC_OPTION(UseParNewGC); +} + // Parse entry point called from JNI_CreateJavaVM jint Arguments::parse(const JavaVMInitArgs* args) { @@ -3328,28 +3374,15 @@ hotspotrc, hotspotrc); } -#if (defined JAVASE_EMBEDDED || defined ARM) - UNSUPPORTED_OPTION(UseG1GC, "G1 GC"); -#endif - #ifdef _ALLBSD_SOURCE // UseLargePages is not yet supported on BSD. UNSUPPORTED_OPTION(UseLargePages, "-XX:+UseLargePages"); #endif -#if !INCLUDE_ALTERNATE_GCS - if (UseParallelGC) { - warning("Parallel GC is not supported in this VM. Using Serial GC."); - } - if (UseParallelOldGC) { - warning("Parallel Old GC is not supported in this VM. Using Serial GC."); - } - if (UseConcMarkSweepGC) { - warning("Concurrent Mark Sweep GC is not supported in this VM. Using Serial GC."); - } - if (UseParNewGC) { - warning("Par New GC is not supported in this VM. Using Serial GC."); - } -#endif // INCLUDE_ALTERNATE_GCS +#if INCLUDE_ALL_GCS + #if (defined JAVASE_EMBEDDED || defined ARM) + UNSUPPORTED_OPTION(UseG1GC, "G1 GC"); + #endif +#endif #ifndef PRODUCT if (TraceBytecodesAt != 0) { @@ -3396,9 +3429,9 @@ // Set object alignment values. set_object_alignment(); -#ifdef SERIALGC +#if !INCLUDE_ALL_GCS force_serial_gc(); -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS #if !INCLUDE_CDS no_shared_spaces(); #endif // INCLUDE_CDS @@ -3426,7 +3459,7 @@ // Set heap size based on available physical memory set_heap_size(); -#if INCLUDE_ALTERNATE_GCS +#if INCLUDE_ALL_GCS // Set per-collector flags if (UseParallelGC || UseParallelOldGC) { set_parallel_gc_flags(); @@ -3438,11 +3471,9 @@ set_g1_gc_flags(); } check_deprecated_gcs(); -#endif // INCLUDE_ALTERNATE_GCS - -#ifdef SERIALGC +#else // INCLUDE_ALL_GCS assert(verify_serial_gc_flags(), "SerialGC unset"); -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS // Set bytecode rewriting flags set_bytecode_flags(); @@ -3539,7 +3570,7 @@ } jint Arguments::adjust_after_os() { -#if INCLUDE_ALTERNATE_GCS +#if INCLUDE_ALL_GCS if (UseParallelGC || UseParallelOldGC) { if (UseNUMA) { if (FLAG_IS_DEFAULT(MinHeapDeltaBytes)) { @@ -3550,7 +3581,7 @@ UseNUMAInterleaving = true; } } -#endif +#endif // INCLUDE_ALL_GCS return JNI_OK; } @@ -3645,36 +3676,6 @@ PropertyList_add(plist, k, v); } -#ifdef KERNEL -char *Arguments::get_kernel_properties() { - // Find properties starting with kernel and append them to string - // We need to find out how long they are first because the URL's that they - // might point to could get long. - int length = 0; - SystemProperty* prop; - for (prop = _system_properties; prop != NULL; prop = prop->next()) { - if (strncmp(prop->key(), "kernel.", 7 ) == 0) { - length += (strlen(prop->key()) + strlen(prop->value()) + 5); // "-D =" - } - } - // Add one for null terminator. - char *props = AllocateHeap(length + 1, mtInternal); - if (length != 0) { - int pos = 0; - for (prop = _system_properties; prop != NULL; prop = prop->next()) { - if (strncmp(prop->key(), "kernel.", 7 ) == 0) { - jio_snprintf(&props[pos], length-pos, - "-D%s=%s ", prop->key(), prop->value()); - pos = strlen(props); - } - } - } - // null terminate props in case of null - props[length] = '\0'; - return props; -} -#endif // KERNEL - // Copies src into buf, replacing "%%" with "%" and "%p" with pid // Returns true if all of the source pointed by src has been copied over to // the destination buffer pointed by buf. Otherwise, returns false. diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/runtime/arguments.hpp --- a/src/share/vm/runtime/arguments.hpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/runtime/arguments.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -561,11 +561,6 @@ // Utility: copies src into buf, replacing "%%" with "%" and "%p" with pid. static bool copy_expand_pid(const char* src, size_t srclen, char* buf, size_t buflen); - -#ifdef KERNEL - // For java kernel vm, return property string for kernel properties. - static char *get_kernel_properties(); -#endif // KERNEL }; #endif // SHARE_VM_RUNTIME_ARGUMENTS_HPP diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/runtime/atomic.hpp --- a/src/share/vm/runtime/atomic.hpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/runtime/atomic.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -29,10 +29,17 @@ class Atomic : AllStatic { public: + // Atomic operations on jlong types are not available on all 32-bit + // platforms. If atomic ops on jlongs are defined here they must only + // be used from code that verifies they are available at runtime and + // can provide an alternative action if not - see supports_cx8() for + // a means to test availability. + // Atomically store to a location inline static void store (jbyte store_value, jbyte* dest); inline static void store (jshort store_value, jshort* dest); inline static void store (jint store_value, jint* dest); + // See comment above about using jlong atomics on 32-bit platforms inline static void store (jlong store_value, jlong* dest); inline static void store_ptr(intptr_t store_value, intptr_t* dest); inline static void store_ptr(void* store_value, void* dest); @@ -40,17 +47,19 @@ inline static void store (jbyte store_value, volatile jbyte* dest); inline static void store (jshort store_value, volatile jshort* dest); inline static void store (jint store_value, volatile jint* dest); + // See comment above about using jlong atomics on 32-bit platforms inline static void store (jlong store_value, volatile jlong* dest); inline static void store_ptr(intptr_t store_value, volatile intptr_t* dest); inline static void store_ptr(void* store_value, volatile void* dest); + // See comment above about using jlong atomics on 32-bit platforms inline static jlong load(volatile jlong* src); // Atomically add to a location, return updated value inline static jint add (jint add_value, volatile jint* dest); inline static intptr_t add_ptr(intptr_t add_value, volatile intptr_t* dest); inline static void* add_ptr(intptr_t add_value, volatile void* dest); - + // See comment above about using jlong atomics on 32-bit platforms static jlong add (jlong add_value, volatile jlong* dest); // Atomically increment location @@ -75,6 +84,7 @@ // barrier across the cmpxchg. I.e., it's really a 'fence_cmpxchg_acquire'. static jbyte cmpxchg (jbyte exchange_value, volatile jbyte* dest, jbyte compare_value); inline static jint cmpxchg (jint exchange_value, volatile jint* dest, jint compare_value); + // See comment above about using jlong atomics on 32-bit platforms inline static jlong cmpxchg (jlong exchange_value, volatile jlong* dest, jlong compare_value); static unsigned int cmpxchg(unsigned int exchange_value, diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/runtime/deoptimization.cpp --- a/src/share/vm/runtime/deoptimization.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/runtime/deoptimization.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -1623,7 +1623,7 @@ if (trap_method() == nm->method()) { make_not_compilable = true; } else { - trap_method->set_not_compilable(CompLevel_full_optimization); + trap_method->set_not_compilable(CompLevel_full_optimization, true, "overflow_recompile_count > PerBytecodeRecompilationCutoff"); // But give grace to the enclosing nm->method(). } } diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/runtime/fieldDescriptor.cpp --- a/src/share/vm/runtime/fieldDescriptor.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/runtime/fieldDescriptor.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -67,13 +67,10 @@ AnnotationArray* fieldDescriptor::type_annotations() const { InstanceKlass* ik = field_holder(); - Annotations* type_annos = ik->type_annotations(); + Array* type_annos = ik->fields_type_annotations(); if (type_annos == NULL) return NULL; - Array* md = type_annos->fields_annotations(); - if (md == NULL) - return NULL; - return md->at(index()); + return type_annos->at(index()); } constantTag fieldDescriptor::initial_value_tag() const { diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/runtime/fprofiler.hpp --- a/src/share/vm/runtime/fprofiler.hpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/runtime/fprofiler.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -25,6 +25,7 @@ #ifndef SHARE_VM_RUNTIME_FPROFILER_HPP #define SHARE_VM_RUNTIME_FPROFILER_HPP +#include "utilities/macros.hpp" #include "runtime/timer.hpp" // a simple flat profiler for Java diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/runtime/globals.cpp --- a/src/share/vm/runtime/globals.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/runtime/globals.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,10 +29,11 @@ #include "runtime/globals.hpp" #include "runtime/globals_extension.hpp" #include "utilities/ostream.hpp" +#include "utilities/macros.hpp" #include "utilities/top.hpp" -#ifndef SERIALGC +#if INCLUDE_ALL_GCS #include "gc_implementation/g1/g1_globals.hpp" -#endif +#endif // INCLUDE_ALL_GCS #ifdef COMPILER1 #include "c1/c1_globals.hpp" #endif @@ -71,7 +72,10 @@ } bool Flag::is_unlocked() const { - if (strcmp(kind, "{diagnostic}") == 0) { + if (strcmp(kind, "{diagnostic}") == 0 || + strcmp(kind, "{C2 diagnostic}") == 0 || + strcmp(kind, "{ARCH diagnostic}") == 0 || + strcmp(kind, "{Shark diagnostic}") == 0) { if (strcmp(name, "EnableInvokeDynamic") == 0 && UnlockExperimentalVMOptions && !UnlockDiagnosticVMOptions) { // transitional logic to allow tests to run until they are changed static int warned; @@ -80,7 +84,9 @@ } return UnlockDiagnosticVMOptions; } else if (strcmp(kind, "{experimental}") == 0 || - strcmp(kind, "{C2 experimental}") == 0) { + strcmp(kind, "{C2 experimental}") == 0 || + strcmp(kind, "{ARCH experimental}") == 0 || + strcmp(kind, "{Shark experimental}") == 0) { return UnlockExperimentalVMOptions; } else { return is_unlocked_ext(); @@ -271,9 +277,9 @@ static Flag flagTable[] = { RUNTIME_FLAGS(RUNTIME_DEVELOP_FLAG_STRUCT, RUNTIME_PD_DEVELOP_FLAG_STRUCT, RUNTIME_PRODUCT_FLAG_STRUCT, RUNTIME_PD_PRODUCT_FLAG_STRUCT, RUNTIME_DIAGNOSTIC_FLAG_STRUCT, RUNTIME_EXPERIMENTAL_FLAG_STRUCT, RUNTIME_NOTPRODUCT_FLAG_STRUCT, RUNTIME_MANAGEABLE_FLAG_STRUCT, RUNTIME_PRODUCT_RW_FLAG_STRUCT, RUNTIME_LP64_PRODUCT_FLAG_STRUCT) RUNTIME_OS_FLAGS(RUNTIME_DEVELOP_FLAG_STRUCT, RUNTIME_PD_DEVELOP_FLAG_STRUCT, RUNTIME_PRODUCT_FLAG_STRUCT, RUNTIME_PD_PRODUCT_FLAG_STRUCT, RUNTIME_DIAGNOSTIC_FLAG_STRUCT, RUNTIME_NOTPRODUCT_FLAG_STRUCT) -#ifndef SERIALGC +#if INCLUDE_ALL_GCS G1_FLAGS(RUNTIME_DEVELOP_FLAG_STRUCT, RUNTIME_PD_DEVELOP_FLAG_STRUCT, RUNTIME_PRODUCT_FLAG_STRUCT, RUNTIME_PD_PRODUCT_FLAG_STRUCT, RUNTIME_DIAGNOSTIC_FLAG_STRUCT, RUNTIME_EXPERIMENTAL_FLAG_STRUCT, RUNTIME_NOTPRODUCT_FLAG_STRUCT, RUNTIME_MANAGEABLE_FLAG_STRUCT, RUNTIME_PRODUCT_RW_FLAG_STRUCT) -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS #ifdef COMPILER1 C1_FLAGS(C1_DEVELOP_FLAG_STRUCT, C1_PD_DEVELOP_FLAG_STRUCT, C1_PRODUCT_FLAG_STRUCT, C1_PD_PRODUCT_FLAG_STRUCT, C1_NOTPRODUCT_FLAG_STRUCT) #endif diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/runtime/globals.hpp --- a/src/share/vm/runtime/globals.hpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/runtime/globals.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1822,7 +1822,7 @@ product(bool, ParallelRefProcBalancingEnabled, true, \ "Enable balancing of reference processing queues") \ \ - product(intx, CMSTriggerRatio, 80, \ + product(uintx, CMSTriggerRatio, 80, \ "Percentage of MinHeapFreeRatio in CMS generation that is " \ "allocated before a CMS collection cycle commences") \ \ @@ -1836,7 +1836,7 @@ \ product(uintx, InitiatingHeapOccupancyPercent, 45, \ "Percentage of the (entire) heap occupancy to start a " \ - "concurrent GC cycle. It us used by GCs that trigger a " \ + "concurrent GC cycle. It is used by GCs that trigger a " \ "concurrent GC cycle based on the occupancy of the entire heap, " \ "not just one of the generations (e.g., G1). A value of 0 " \ "denotes 'do constant GC cycles'.") \ @@ -3003,10 +3003,10 @@ product(uintx, TLABWasteIncrement, 4, \ "Increment allowed waste at slow allocation") \ \ - product(intx, SurvivorRatio, 8, \ + product(uintx, SurvivorRatio, 8, \ "Ratio of eden/survivor space size") \ \ - product(intx, NewRatio, 2, \ + product(uintx, NewRatio, 2, \ "Ratio of new/old generation sizes") \ \ product_pd(uintx, NewSizeThreadIncrease, \ @@ -3036,10 +3036,16 @@ "Min change in heap space due to GC (in bytes)") \ \ product(uintx, MinMetaspaceExpansion, ScaleForWordSize(256*K), \ - "Min expansion of permanent heap (in bytes)") \ + "Min expansion of Metaspace (in bytes)") \ + \ + product(uintx, MinMetaspaceFreeRatio, 40, \ + "Min percentage of Metaspace free after GC to avoid expansion") \ + \ + product(uintx, MaxMetaspaceFreeRatio, 70, \ + "Max percentage of Metaspace free after GC to avoid shrinking") \ \ product(uintx, MaxMetaspaceExpansion, ScaleForWordSize(4*M), \ - "Max expansion of permanent heap without full GC (in bytes)") \ + "Max expansion of Metaspace without full GC (in bytes)") \ \ product(intx, QueuedAllocationWarningCount, 0, \ "Number of times an allocation that queues behind a GC " \ @@ -3057,7 +3063,7 @@ product(uintx, InitialTenuringThreshold, 7, \ "Initial value for tenuring threshold") \ \ - product(intx, TargetSurvivorRatio, 50, \ + product(uintx, TargetSurvivorRatio, 50, \ "Desired percentage of survivor space used after scavenge") \ \ product(uintx, MarkSweepDeadRatio, 5, \ diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/runtime/globals_extension.hpp --- a/src/share/vm/runtime/globals_extension.hpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/runtime/globals_extension.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -26,6 +26,7 @@ #define SHARE_VM_RUNTIME_GLOBALS_EXTENSION_HPP #include "runtime/globals.hpp" +#include "utilities/macros.hpp" #include "utilities/top.hpp" // Construct enum of Flag_ constants. @@ -106,9 +107,9 @@ typedef enum { RUNTIME_FLAGS(RUNTIME_DEVELOP_FLAG_MEMBER, RUNTIME_PD_DEVELOP_FLAG_MEMBER, RUNTIME_PRODUCT_FLAG_MEMBER, RUNTIME_PD_PRODUCT_FLAG_MEMBER, RUNTIME_DIAGNOSTIC_FLAG_MEMBER, RUNTIME_EXPERIMENTAL_FLAG_MEMBER, RUNTIME_NOTPRODUCT_FLAG_MEMBER, RUNTIME_MANAGEABLE_FLAG_MEMBER, RUNTIME_PRODUCT_RW_FLAG_MEMBER, RUNTIME_LP64_PRODUCT_FLAG_MEMBER) RUNTIME_OS_FLAGS(RUNTIME_DEVELOP_FLAG_MEMBER, RUNTIME_PD_DEVELOP_FLAG_MEMBER, RUNTIME_PRODUCT_FLAG_MEMBER, RUNTIME_PD_PRODUCT_FLAG_MEMBER, RUNTIME_DIAGNOSTIC_FLAG_MEMBER, RUNTIME_NOTPRODUCT_FLAG_MEMBER) -#if INCLUDE_ALTERNATE_GCS +#if INCLUDE_ALL_GCS G1_FLAGS(RUNTIME_DEVELOP_FLAG_MEMBER, RUNTIME_PD_DEVELOP_FLAG_MEMBER, RUNTIME_PRODUCT_FLAG_MEMBER, RUNTIME_PD_PRODUCT_FLAG_MEMBER, RUNTIME_DIAGNOSTIC_FLAG_MEMBER, RUNTIME_EXPERIMENTAL_FLAG_MEMBER, RUNTIME_NOTPRODUCT_FLAG_MEMBER, RUNTIME_MANAGEABLE_FLAG_MEMBER, RUNTIME_PRODUCT_RW_FLAG_MEMBER) -#endif // INCLUDE_ALTERNATE_GCS +#endif // INCLUDE_ALL_GCS #ifdef COMPILER1 C1_FLAGS(C1_DEVELOP_FLAG_MEMBER, C1_PD_DEVELOP_FLAG_MEMBER, C1_PRODUCT_FLAG_MEMBER, C1_PD_PRODUCT_FLAG_MEMBER, C1_NOTPRODUCT_FLAG_MEMBER) #endif @@ -213,7 +214,7 @@ RUNTIME_PD_PRODUCT_FLAG_MEMBER_WITH_TYPE, RUNTIME_DIAGNOSTIC_FLAG_MEMBER_WITH_TYPE, RUNTIME_NOTPRODUCT_FLAG_MEMBER_WITH_TYPE) -#if INCLUDE_ALTERNATE_GCS +#if INCLUDE_ALL_GCS G1_FLAGS(RUNTIME_DEVELOP_FLAG_MEMBER_WITH_TYPE, RUNTIME_PD_DEVELOP_FLAG_MEMBER_WITH_TYPE, RUNTIME_PRODUCT_FLAG_MEMBER_WITH_TYPE, @@ -223,7 +224,7 @@ RUNTIME_NOTPRODUCT_FLAG_MEMBER_WITH_TYPE, RUNTIME_MANAGEABLE_FLAG_MEMBER_WITH_TYPE, RUNTIME_PRODUCT_RW_FLAG_MEMBER_WITH_TYPE) -#endif // INCLUDE_ALTERNATE_GCS +#endif // INCLUDE_ALL_GCS #ifdef COMPILER1 C1_FLAGS(C1_DEVELOP_FLAG_MEMBER_WITH_TYPE, C1_PD_DEVELOP_FLAG_MEMBER_WITH_TYPE, diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/runtime/init.cpp --- a/src/share/vm/runtime/init.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/runtime/init.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -34,7 +34,7 @@ #include "runtime/init.hpp" #include "runtime/safepoint.hpp" #include "runtime/sharedRuntime.hpp" -#include "utilities/machineCodePrinter.hpp" +#include "utilities/macros.hpp" // Initialization done by VM thread in vm_init_globals() void check_ThreadShadow(); diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/runtime/java.cpp --- a/src/share/vm/runtime/java.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/runtime/java.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -67,6 +67,7 @@ #include "utilities/dtrace.hpp" #include "utilities/globalDefinitions.hpp" #include "utilities/histogram.hpp" +#include "utilities/macros.hpp" #include "utilities/vmError.hpp" #ifdef TARGET_ARCH_x86 # include "vm_version_x86.hpp" @@ -83,11 +84,11 @@ #ifdef TARGET_ARCH_ppc # include "vm_version_ppc.hpp" #endif -#ifndef SERIALGC +#if INCLUDE_ALL_GCS #include "gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.hpp" #include "gc_implementation/parallelScavenge/psScavenge.hpp" #include "gc_implementation/parallelScavenge/psScavenge.inline.hpp" -#endif +#endif // INCLUDE_ALL_GCS #ifdef COMPILER1 #include "c1/c1_Compiler.hpp" #include "c1/c1_Runtime1.hpp" diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/runtime/os.cpp --- a/src/share/vm/runtime/os.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/runtime/os.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -985,15 +985,28 @@ // if C stack is walkable beyond current frame. The check for fp() is not // necessary on Sparc, but it's harmless. bool os::is_first_C_frame(frame* fr) { -#ifdef IA64 - // In order to walk native frames on Itanium, we need to access the unwind - // table, which is inside ELF. We don't want to parse ELF after fatal error, - // so return true for IA64. If we need to support C stack walking on IA64, - // this function needs to be moved to CPU specific files, as fp() on IA64 - // is register stack, which grows towards higher memory address. +#if defined(IA64) && !defined(_WIN32) + // On IA64 we have to check if the callers bsp is still valid + // (i.e. within the register stack bounds). + // Notice: this only works for threads created by the VM and only if + // we walk the current stack!!! If we want to be able to walk + // arbitrary other threads, we'll have to somehow store the thread + // object in the frame. + Thread *thread = Thread::current(); + if ((address)fr->fp() <= + thread->register_stack_base() HPUX_ONLY(+ 0x0) LINUX_ONLY(+ 0x50)) { + // This check is a little hacky, because on Linux the first C + // frame's ('start_thread') register stack frame starts at + // "register_stack_base + 0x48" while on HPUX, the first C frame's + // ('__pthread_bound_body') register stack frame seems to really + // start at "register_stack_base". + return true; + } else { + return false; + } +#elif defined(IA64) && defined(_WIN32) return true; -#endif - +#else // Load up sp, fp, sender sp and sender fp, check for reasonable values. // Check usp first, because if that's bad the other accessors may fault // on some architectures. Ditto ufp second, etc. @@ -1023,6 +1036,7 @@ if (old_fp - ufp > 64 * K) return true; return false; +#endif } #ifdef ASSERT diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/runtime/safepoint.cpp --- a/src/share/vm/runtime/safepoint.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/runtime/safepoint.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -52,6 +52,7 @@ #include "services/memTracker.hpp" #include "services/runtimeService.hpp" #include "utilities/events.hpp" +#include "utilities/macros.hpp" #ifdef TARGET_ARCH_x86 # include "nativeInst_x86.hpp" # include "vmreg_x86.inline.hpp" @@ -72,10 +73,10 @@ # include "nativeInst_ppc.hpp" # include "vmreg_ppc.inline.hpp" #endif -#ifndef SERIALGC +#if INCLUDE_ALL_GCS #include "gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.hpp" #include "gc_implementation/shared/concurrentGCThread.hpp" -#endif +#endif // INCLUDE_ALL_GCS #ifdef COMPILER1 #include "c1/c1_globals.hpp" #endif @@ -106,7 +107,7 @@ _ts_of_current_safepoint = tty->time_stamp().seconds(); } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS if (UseConcMarkSweepGC) { // In the future we should investigate whether CMS can use the // more-general mechanism below. DLD (01/05). @@ -114,7 +115,7 @@ } else if (UseG1GC) { ConcurrentGCThread::safepoint_synchronize(); } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS // By getting the Threads_lock, we assure that no threads are about to start or // exit. It is released again in SafepointSynchronize::end(). @@ -483,14 +484,14 @@ Threads_lock->unlock(); } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS // If there are any concurrent GC threads resume them. if (UseConcMarkSweepGC) { ConcurrentMarkSweepThread::desynchronize(false); } else if (UseG1GC) { ConcurrentGCThread::safepoint_desynchronize(); } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS // record this time so VMThread can keep track how much time has elasped // since last safepoint. _end_of_last_safepoint = os::javaTimeMillis(); diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/runtime/sharedRuntime.cpp --- a/src/share/vm/runtime/sharedRuntime.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/runtime/sharedRuntime.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -56,6 +56,7 @@ #include "utilities/dtrace.hpp" #include "utilities/events.hpp" #include "utilities/hashtable.inline.hpp" +#include "utilities/macros.hpp" #include "utilities/xmlstream.hpp" #ifdef TARGET_ARCH_x86 # include "nativeInst_x86.hpp" @@ -212,7 +213,7 @@ } #endif // PRODUCT -#ifndef SERIALGC +#if INCLUDE_ALL_GCS // G1 write-barrier pre: executed before a pointer store. JRT_LEAF(void, SharedRuntime::g1_wb_pre(oopDesc* orig, JavaThread *thread)) @@ -230,7 +231,7 @@ thread->dirty_card_queue().enqueue(card_addr); JRT_END -#endif // !SERIALGC +#endif // INCLUDE_ALL_GCS JRT_LEAF(jlong, SharedRuntime::lmul(jlong y, jlong x)) @@ -2868,10 +2869,6 @@ JRT_LEAF(intptr_t*, SharedRuntime::OSR_migration_begin( JavaThread *thread) ) -#ifdef IA64 - ShouldNotReachHere(); // NYI -#endif /* IA64 */ - // // This code is dependent on the memory layout of the interpreter local // array and the monitors. On all of our platforms the layout is identical diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/runtime/sharedRuntime.hpp --- a/src/share/vm/runtime/sharedRuntime.hpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/runtime/sharedRuntime.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -32,6 +32,7 @@ #include "memory/resourceArea.hpp" #include "runtime/threadLocalStorage.hpp" #include "utilities/hashtable.hpp" +#include "utilities/macros.hpp" class AdapterHandlerEntry; class AdapterHandlerTable; @@ -168,11 +169,11 @@ static address raw_exception_handler_for_return_address(JavaThread* thread, address return_address); static address exception_handler_for_return_address(JavaThread* thread, address return_address); -#ifndef SERIALGC +#if INCLUDE_ALL_GCS // G1 write barriers static void g1_wb_pre(oopDesc* orig, JavaThread *thread); static void g1_wb_post(void* card_addr, JavaThread* thread); -#endif // !SERIALGC +#endif // INCLUDE_ALL_GCS // exception handling and implicit exceptions static address compute_compiled_exc_handler(nmethod* nm, address ret_pc, Handle& exception, diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/runtime/synchronizer.cpp --- a/src/share/vm/runtime/synchronizer.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/runtime/synchronizer.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -53,7 +53,7 @@ # include "os_bsd.inline.hpp" #endif -#if defined(__GNUC__) && !defined(IA64) +#if defined(__GNUC__) // Need to inhibit inlining for older versions of GCC to avoid build-time failures #define ATTR __attribute__((noinline)) #else diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/runtime/thread.cpp --- a/src/share/vm/runtime/thread.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/runtime/thread.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -85,6 +85,7 @@ #include "utilities/dtrace.hpp" #include "utilities/events.hpp" #include "utilities/preserveException.hpp" +#include "utilities/macros.hpp" #ifdef TARGET_OS_FAMILY_linux # include "os_linux.inline.hpp" #endif @@ -97,11 +98,11 @@ #ifdef TARGET_OS_FAMILY_bsd # include "os_bsd.inline.hpp" #endif -#ifndef SERIALGC +#if INCLUDE_ALL_GCS #include "gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.hpp" #include "gc_implementation/g1/concurrentMarkThread.inline.hpp" #include "gc_implementation/parallelScavenge/pcTasks.hpp" -#endif +#endif // INCLUDE_ALL_GCS #ifdef COMPILER1 #include "c1/c1_Compiler.hpp" #endif @@ -1495,17 +1496,17 @@ pd_initialize(); } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS SATBMarkQueueSet JavaThread::_satb_mark_queue_set; DirtyCardQueueSet JavaThread::_dirty_card_queue_set; -#endif // !SERIALGC +#endif // INCLUDE_ALL_GCS JavaThread::JavaThread(bool is_attaching_via_jni) : Thread() -#ifndef SERIALGC +#if INCLUDE_ALL_GCS , _satb_mark_queue(&_satb_mark_queue_set), _dirty_card_queue(&_dirty_card_queue_set) -#endif // !SERIALGC +#endif // INCLUDE_ALL_GCS { initialize(); if (is_attaching_via_jni) { @@ -1513,7 +1514,7 @@ } else { _jni_attach_state = _not_attaching_via_jni; } - assert(_deferred_card_mark.is_empty(), "Default MemRegion ctor"); + assert(deferred_card_mark().is_empty(), "Default MemRegion ctor"); _safepoint_visible = false; } @@ -1560,10 +1561,10 @@ JavaThread::JavaThread(ThreadFunction entry_point, size_t stack_sz) : Thread() -#ifndef SERIALGC +#if INCLUDE_ALL_GCS , _satb_mark_queue(&_satb_mark_queue_set), _dirty_card_queue(&_dirty_card_queue_set) -#endif // !SERIALGC +#endif // INCLUDE_ALL_GCS { if (TraceThreadEvents) { tty->print_cr("creating thread %p", this); @@ -1909,19 +1910,26 @@ JvmtiExport::cleanup_thread(this); } -#ifndef SERIALGC - // We must flush G1-related buffers before removing a thread from + // We must flush any deferred card marks before removing a thread from // the list of active threads. + Universe::heap()->flush_deferred_store_barrier(this); + assert(deferred_card_mark().is_empty(), "Should have been flushed"); + +#if INCLUDE_ALL_GCS + // We must flush the G1-related buffers before removing a thread + // from the list of active threads. We must do this after any deferred + // card marks have been flushed (above) so that any entries that are + // added to the thread's dirty card queue as a result are not lost. if (UseG1GC) { flush_barrier_queues(); } -#endif +#endif // INCLUDE_ALL_GCS // Remove from list of active threads list, and notify VM thread if we are the last non-daemon thread Threads::remove(this); } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS // Flush G1-related queues. void JavaThread::flush_barrier_queues() { satb_mark_queue().flush(); @@ -1949,7 +1957,7 @@ // active field set to true. assert(dirty_queue.is_active(), "dirty card queue should be active"); } -#endif // !SERIALGC +#endif // INCLUDE_ALL_GCS void JavaThread::cleanup_failed_attach_current_thread() { if (get_thread_profiler() != NULL) { @@ -1977,11 +1985,11 @@ tlab().make_parsable(true); // retire TLAB, if any } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS if (UseG1GC) { flush_barrier_queues(); } -#endif +#endif // INCLUDE_ALL_GCS Threads::remove(this); delete this; @@ -3609,7 +3617,7 @@ vm_exit_during_initialization(Handle(THREAD, PENDING_EXCEPTION)); } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS // Support for ConcurrentMarkSweep. This should be cleaned up // and better encapsulated. The ugly nested if test would go away // once things are properly refactored. XXX YSR @@ -3623,7 +3631,7 @@ vm_exit_during_initialization(Handle(THREAD, PENDING_EXCEPTION)); } } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS // Always call even when there are not JVMTI environments yet, since environments // may be attached late and JVMTI must track phases of VM execution @@ -3748,28 +3756,6 @@ name)) { library = os::dll_load(buffer, ebuf, sizeof ebuf); } -#ifdef KERNEL - // Download instrument dll - if (library == NULL && strcmp(name, "instrument") == 0) { - char *props = Arguments::get_kernel_properties(); - char *home = Arguments::get_java_home(); - const char *fmt = "%s/bin/java %s -Dkernel.background.download=false" - " sun.jkernel.DownloadManager -download client_jvm"; - size_t length = strlen(props) + strlen(home) + strlen(fmt) + 1; - char *cmd = NEW_C_HEAP_ARRAY(char, length, mtThread); - jio_snprintf(cmd, length, fmt, home, props); - int status = os::fork_and_exec(cmd); - FreeHeap(props); - if (status == -1) { - warning(cmd); - vm_exit_during_initialization("fork_and_exec failed: %s", - strerror(errno)); - } - FREE_C_HEAP_ARRAY(char, cmd, mtThread); - // when this comes back the instrument.dll should be where it belongs. - library = os::dll_load(buffer, ebuf, sizeof ebuf); - } -#endif // KERNEL if (library == NULL) { // Try the local directory char ns[1] = {0}; if (os::dll_build_name(buffer, sizeof(buffer), ns, name)) { @@ -4218,7 +4204,7 @@ } } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS // Used by ParallelScavenge void Threads::create_thread_roots_tasks(GCTaskQueue* q) { ALL_JAVA_THREADS(p) { @@ -4234,7 +4220,7 @@ } q->enqueue(new ThreadRootsMarkingTask(VMThread::vm_thread())); } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS void Threads::nmethods_do(CodeBlobClosure* cf) { ALL_JAVA_THREADS(p) { @@ -4342,13 +4328,13 @@ ); st->cr(); -#ifndef SERIALGC +#if INCLUDE_ALL_GCS // Dump concurrent locks ConcurrentLocksDump concurrent_locks; if (print_concurrent_locks) { concurrent_locks.dump_at_safepoint(); } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS ALL_JAVA_THREADS(p) { ResourceMark rm; @@ -4361,11 +4347,11 @@ } } st->cr(); -#ifndef SERIALGC +#if INCLUDE_ALL_GCS if (print_concurrent_locks) { concurrent_locks.print_locks_on(p, st); } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS } VMThread::vm_thread()->print_on(st); diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/runtime/thread.hpp --- a/src/share/vm/runtime/thread.hpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/runtime/thread.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -41,6 +41,7 @@ #include "runtime/stubRoutines.hpp" #include "runtime/threadLocalStorage.hpp" #include "runtime/unhandledOops.hpp" +#include "utilities/macros.hpp" #if INCLUDE_NMT #include "services/memRecorder.hpp" @@ -49,10 +50,10 @@ #include "trace/tracing.hpp" #include "utilities/exceptions.hpp" #include "utilities/top.hpp" -#ifndef SERIALGC +#if INCLUDE_ALL_GCS #include "gc_implementation/g1/dirtyCardQueue.hpp" #include "gc_implementation/g1/satbQueue.hpp" -#endif +#endif // INCLUDE_ALL_GCS #ifdef ZERO #ifdef TARGET_ARCH_zero # include "stack_zero.hpp" @@ -943,7 +944,7 @@ } _jmp_ring[ jump_ring_buffer_size ]; #endif /* PRODUCT */ -#ifndef SERIALGC +#if INCLUDE_ALL_GCS // Support for G1 barriers ObjPtrQueue _satb_mark_queue; // Thread-local log for SATB barrier. @@ -955,7 +956,7 @@ static DirtyCardQueueSet _dirty_card_queue_set; void flush_barrier_queues(); -#endif // !SERIALGC +#endif // INCLUDE_ALL_GCS friend class VMThread; friend class ThreadWaitTransition; @@ -1388,10 +1389,10 @@ return byte_offset_of(JavaThread, _should_post_on_exceptions_flag); } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS static ByteSize satb_mark_queue_offset() { return byte_offset_of(JavaThread, _satb_mark_queue); } static ByteSize dirty_card_queue_offset() { return byte_offset_of(JavaThread, _dirty_card_queue); } -#endif // !SERIALGC +#endif // INCLUDE_ALL_GCS // Returns the jni environment for this thread JNIEnv* jni_environment() { return &_jni_environment; } @@ -1680,7 +1681,7 @@ _stack_size_at_create = value; } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS // SATB marking queue support ObjPtrQueue& satb_mark_queue() { return _satb_mark_queue; } static SATBMarkQueueSet& satb_mark_queue_set() { @@ -1692,7 +1693,7 @@ static DirtyCardQueueSet& dirty_card_queue_set() { return _dirty_card_queue_set; } -#endif // !SERIALGC +#endif // INCLUDE_ALL_GCS // This method initializes the SATB and dirty card queues before a // JavaThread is added to the Java thread list. Right now, we don't @@ -1711,11 +1712,11 @@ // might happen between the JavaThread constructor being called and the // thread being added to the Java thread list (an example of this is // when the structure for the DestroyJavaVM thread is created). -#ifndef SERIALGC +#if INCLUDE_ALL_GCS void initialize_queues(); -#else // !SERIALGC +#else // INCLUDE_ALL_GCS void initialize_queues() { } -#endif // !SERIALGC +#endif // INCLUDE_ALL_GCS // Machine dependent stuff #ifdef TARGET_OS_ARCH_linux_x86 diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/runtime/vframeArray.cpp --- a/src/share/vm/runtime/vframeArray.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/runtime/vframeArray.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -233,8 +233,6 @@ // Force early return from top frame after deoptimization #ifndef CC_INTERP pc = Interpreter::remove_activation_early_entry(state->earlyret_tos()); -#else - // TBD: Need to implement ForceEarlyReturn for CC_INTERP (ia64) #endif } else { // Possibly override the previous pc computation of the top (youngest) frame diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/runtime/vmStructs.cpp --- a/src/share/vm/runtime/vmStructs.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/runtime/vmStructs.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -101,6 +101,7 @@ #include "utilities/array.hpp" #include "utilities/globalDefinitions.hpp" #include "utilities/hashtable.hpp" +#include "utilities/macros.hpp" #ifdef TARGET_ARCH_x86 # include "vmStructs_x86.hpp" #endif @@ -146,7 +147,7 @@ #ifdef TARGET_OS_ARCH_bsd_zero # include "vmStructs_bsd_zero.hpp" #endif -#ifndef SERIALGC +#if INCLUDE_ALL_GCS #include "gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp" #include "gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp" #include "gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.hpp" @@ -161,7 +162,7 @@ #include "gc_implementation/parallelScavenge/psYoungGen.hpp" #include "gc_implementation/parallelScavenge/vmStructs_parallelgc.hpp" #include "gc_implementation/g1/vmStructs_g1.hpp" -#endif +#endif // INCLUDE_ALL_GCS #ifdef COMPILER2 #include "opto/addnode.hpp" #include "opto/block.hpp" @@ -365,11 +366,10 @@ volatile_nonstatic_field(Method, _from_compiled_entry, address) \ volatile_nonstatic_field(Method, _from_interpreted_entry, address) \ volatile_nonstatic_field(ConstMethod, _fingerprint, uint64_t) \ - nonstatic_field(ConstMethod, _constants, ConstantPool*) \ + nonstatic_field(ConstMethod, _constants, ConstantPool*) \ nonstatic_field(ConstMethod, _stackmap_data, Array*) \ nonstatic_field(ConstMethod, _constMethod_size, int) \ - nonstatic_field(ConstMethod, _interpreter_kind, jbyte) \ - nonstatic_field(ConstMethod, _flags, jbyte) \ + nonstatic_field(ConstMethod, _flags, u2) \ nonstatic_field(ConstMethod, _code_size, u2) \ nonstatic_field(ConstMethod, _name_index, u2) \ nonstatic_field(ConstMethod, _signature_index, u2) \ @@ -1161,6 +1161,7 @@ static_field(Abstract_VM_Version, _vm_major_version, int) \ static_field(Abstract_VM_Version, _vm_minor_version, int) \ static_field(Abstract_VM_Version, _vm_build_number, int) \ + static_field(Abstract_VM_Version, _reserve_for_allocation_prefetch, int) \ \ static_field(JDK_Version, _current, JDK_Version) \ nonstatic_field(JDK_Version, _partially_initialized, bool) \ @@ -2087,8 +2088,7 @@ declare_toplevel_type(FreeBlockDictionary*) \ declare_toplevel_type(FreeList*) \ declare_toplevel_type(FreeList) \ - declare_toplevel_type(MetablockTreeDictionary*) \ - declare_type(MetablockTreeDictionary, FreeBlockDictionary) + declare_type(MetablockTreeDictionary, FreeBlockDictionary) //-------------------------------------------------------------------------------- @@ -2109,8 +2109,6 @@ /* Useful globals */ \ /******************/ \ \ - declare_constant(UseTLAB) \ - declare_constant(EnableInvokeDynamic) \ \ /**************/ \ /* Stack bias */ \ @@ -2260,14 +2258,18 @@ declare_constant(Klass::_lh_array_tag_obj_value) \ \ /********************************/ \ - /* ConstMethod anon-enum */ \ + /* ConstMethod anon-enum */ \ /********************************/ \ \ - declare_constant(ConstMethod::_has_linenumber_table) \ - declare_constant(ConstMethod::_has_checked_exceptions) \ - declare_constant(ConstMethod::_has_localvariable_table) \ - declare_constant(ConstMethod::_has_exception_table) \ - declare_constant(ConstMethod::_has_generic_signature) \ + declare_constant(ConstMethod::_has_linenumber_table) \ + declare_constant(ConstMethod::_has_checked_exceptions) \ + declare_constant(ConstMethod::_has_localvariable_table) \ + declare_constant(ConstMethod::_has_exception_table) \ + declare_constant(ConstMethod::_has_generic_signature) \ + declare_constant(ConstMethod::_has_method_annotations) \ + declare_constant(ConstMethod::_has_parameter_annotations) \ + declare_constant(ConstMethod::_has_default_annotations) \ + declare_constant(ConstMethod::_has_type_annotations) \ \ /*************************************/ \ /* InstanceKlass enum */ \ @@ -2792,7 +2794,7 @@ GENERATE_C1_UNCHECKED_STATIC_VM_STRUCT_ENTRY, GENERATE_C2_UNCHECKED_STATIC_VM_STRUCT_ENTRY) -#ifndef SERIALGC +#if INCLUDE_ALL_GCS VM_STRUCTS_PARALLELGC(GENERATE_NONSTATIC_VM_STRUCT_ENTRY, GENERATE_STATIC_VM_STRUCT_ENTRY) @@ -2802,7 +2804,7 @@ VM_STRUCTS_G1(GENERATE_NONSTATIC_VM_STRUCT_ENTRY, GENERATE_STATIC_VM_STRUCT_ENTRY) -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS VM_STRUCTS_CPU(GENERATE_NONSTATIC_VM_STRUCT_ENTRY, GENERATE_STATIC_VM_STRUCT_ENTRY, @@ -2836,7 +2838,7 @@ GENERATE_C2_VM_TYPE_ENTRY, GENERATE_C2_TOPLEVEL_VM_TYPE_ENTRY) -#ifndef SERIALGC +#if INCLUDE_ALL_GCS VM_TYPES_PARALLELGC(GENERATE_VM_TYPE_ENTRY, GENERATE_TOPLEVEL_VM_TYPE_ENTRY) @@ -2847,7 +2849,7 @@ VM_TYPES_G1(GENERATE_VM_TYPE_ENTRY, GENERATE_TOPLEVEL_VM_TYPE_ENTRY) -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS VM_TYPES_CPU(GENERATE_VM_TYPE_ENTRY, GENERATE_TOPLEVEL_VM_TYPE_ENTRY, @@ -2878,11 +2880,11 @@ GENERATE_C2_VM_INT_CONSTANT_ENTRY, GENERATE_C2_PREPROCESSOR_VM_INT_CONSTANT_ENTRY) -#ifndef SERIALGC +#if INCLUDE_ALL_GCS VM_INT_CONSTANTS_CMS(GENERATE_VM_INT_CONSTANT_ENTRY) VM_INT_CONSTANTS_PARNEW(GENERATE_VM_INT_CONSTANT_ENTRY) -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS VM_INT_CONSTANTS_CPU(GENERATE_VM_INT_CONSTANT_ENTRY, GENERATE_PREPROCESSOR_VM_INT_CONSTANT_ENTRY, @@ -2936,7 +2938,7 @@ CHECK_NO_OP, CHECK_NO_OP); -#ifndef SERIALGC +#if INCLUDE_ALL_GCS VM_STRUCTS_PARALLELGC(CHECK_NONSTATIC_VM_STRUCT_ENTRY, CHECK_STATIC_VM_STRUCT_ENTRY); @@ -2946,7 +2948,7 @@ VM_STRUCTS_G1(CHECK_NONSTATIC_VM_STRUCT_ENTRY, CHECK_STATIC_VM_STRUCT_ENTRY); -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS VM_STRUCTS_CPU(CHECK_NONSTATIC_VM_STRUCT_ENTRY, CHECK_STATIC_VM_STRUCT_ENTRY, @@ -2975,7 +2977,7 @@ CHECK_C2_VM_TYPE_ENTRY, CHECK_C2_TOPLEVEL_VM_TYPE_ENTRY); -#ifndef SERIALGC +#if INCLUDE_ALL_GCS VM_TYPES_PARALLELGC(CHECK_VM_TYPE_ENTRY, CHECK_SINGLE_ARG_VM_TYPE_NO_OP); @@ -2986,7 +2988,7 @@ VM_TYPES_G1(CHECK_VM_TYPE_ENTRY, CHECK_SINGLE_ARG_VM_TYPE_NO_OP); -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS VM_TYPES_CPU(CHECK_VM_TYPE_ENTRY, CHECK_SINGLE_ARG_VM_TYPE_NO_OP, @@ -3041,7 +3043,7 @@ ENSURE_C2_FIELD_TYPE_PRESENT, CHECK_NO_OP, CHECK_NO_OP)); -#ifndef SERIALGC +#if INCLUDE_ALL_GCS debug_only(VM_STRUCTS_PARALLELGC(ENSURE_FIELD_TYPE_PRESENT, ENSURE_FIELD_TYPE_PRESENT)); debug_only(VM_STRUCTS_CMS(ENSURE_FIELD_TYPE_PRESENT, @@ -3049,7 +3051,7 @@ ENSURE_FIELD_TYPE_PRESENT)); debug_only(VM_STRUCTS_G1(ENSURE_FIELD_TYPE_PRESENT, ENSURE_FIELD_TYPE_PRESENT)); -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS debug_only(VM_STRUCTS_CPU(ENSURE_FIELD_TYPE_PRESENT, ENSURE_FIELD_TYPE_PRESENT, CHECK_NO_OP, diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/runtime/vmStructs.hpp --- a/src/share/vm/runtime/vmStructs.hpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/runtime/vmStructs.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,9 +25,7 @@ #ifndef SHARE_VM_RUNTIME_VMSTRUCTS_HPP #define SHARE_VM_RUNTIME_VMSTRUCTS_HPP -#ifndef VM_STRUCTS_KERNEL #include "utilities/debug.hpp" -#endif #ifdef COMPILER1 #include "c1/c1_Runtime1.hpp" #endif diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/runtime/vm_version.cpp --- a/src/share/vm/runtime/vm_version.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/runtime/vm_version.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -111,9 +111,6 @@ #endif #ifndef VMTYPE - #ifdef KERNEL - #define VMTYPE "Kernel" - #else // KERNEL #ifdef TIERED #define VMTYPE "Server" #else // TIERED @@ -132,7 +129,6 @@ #endif // GRAAL #endif // ZERO #endif // TIERED - #endif // KERNEL #endif #ifndef HOTSPOT_VM_DISTRO diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/services/attachListener.cpp --- a/src/share/vm/services/attachListener.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/services/attachListener.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -170,7 +170,6 @@ return JNI_OK; } -#ifndef SERVICES_KERNEL // Heap dumping not supported // Implementation of "dumpheap" command. // See also: HeapDumpDCmd class // @@ -212,7 +211,6 @@ } return JNI_OK; } -#endif // SERVICES_KERNEL // Implementation of "inspectheap" command // See also: ClassHistogramDCmd class @@ -382,9 +380,7 @@ static AttachOperationFunctionInfo funcs[] = { { "agentProperties", get_agent_properties }, { "datadump", data_dump }, -#ifndef SERVICES_KERNEL { "dumpheap", dump_heap }, -#endif // SERVICES_KERNEL { "load", JvmtiExport::load_agent_library }, { "properties", get_system_properties }, { "threaddump", thread_dump }, diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/services/attachListener.hpp --- a/src/share/vm/services/attachListener.hpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/services/attachListener.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,6 +28,7 @@ #include "memory/allocation.hpp" #include "utilities/debug.hpp" #include "utilities/ostream.hpp" +#include "utilities/macros.hpp" // The AttachListener thread services a queue of operations that are enqueued // by client tools. Each operation is identified by a name and has up to 3 @@ -38,8 +39,6 @@ // complets the result value and any result data is returned to the client // tool. -#ifndef SERVICES_KERNEL - class AttachOperation; typedef jint (*AttachOperationFunction)(AttachOperation* op, outputStream* out); @@ -48,7 +47,6 @@ const char* name; AttachOperationFunction func; }; -#endif // SERVICES_KERNEL class AttachListener: AllStatic { public: diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/services/classLoadingService.cpp --- a/src/share/vm/services/classLoadingService.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/services/classLoadingService.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -31,6 +31,7 @@ #include "services/classLoadingService.hpp" #include "services/memoryService.hpp" #include "utilities/dtrace.hpp" +#include "utilities/macros.hpp" #ifdef DTRACE_ENABLED diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/services/classLoadingService.hpp --- a/src/share/vm/services/classLoadingService.hpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/services/classLoadingService.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -28,6 +28,7 @@ #include "runtime/handles.hpp" #include "runtime/perfData.hpp" #include "utilities/growableArray.hpp" +#include "utilities/macros.hpp" class InstanceKlass; diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/services/diagnosticCommand.cpp --- a/src/share/vm/services/diagnosticCommand.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/services/diagnosticCommand.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,6 +30,7 @@ #include "services/diagnosticFramework.hpp" #include "services/heapDumper.hpp" #include "services/management.hpp" +#include "utilities/macros.hpp" void DCmdRegistrant::register_dcmds(){ // Registration of the diagnostic commands @@ -43,12 +44,12 @@ DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(true, false)); DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(true, false)); DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(true, false)); -#if INCLUDE_SERVICES // Heap dumping supported +#if INCLUDE_SERVICES // Heap dumping/inspection supported DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(true, false)); + DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(true, false)); + DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(true, false)); #endif // INCLUDE_SERVICES - DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(true, false)); DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(true, false)); - //Enhanced JMX Agent Support DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(true,false)); DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(true,false)); @@ -252,7 +253,7 @@ vmSymbols::void_method_signature(), CHECK); } -#if INCLUDE_SERVICES // Heap dumping supported +#if INCLUDE_SERVICES // Heap dumping/inspection supported HeapDumpDCmd::HeapDumpDCmd(outputStream* output, bool heap) : DCmdWithParser(output, heap), _filename("filename","Name of the dump file", "STRING",true), @@ -292,7 +293,6 @@ return 0; } } -#endif // INCLUDE_SERVICES ClassHistogramDCmd::ClassHistogramDCmd(outputStream* output, bool heap) : DCmdWithParser(output, heap), @@ -319,6 +319,65 @@ } } +#define DEFAULT_COLUMNS "InstBytes,KlassBytes,CpAll,annotations,MethodCount,Bytecodes,MethodAll,ROAll,RWAll,Total" +ClassStatsDCmd::ClassStatsDCmd(outputStream* output, bool heap) : + DCmdWithParser(output, heap), + _csv("-csv", "Print in CSV (comma-separated values) format for spreadsheets", + "BOOLEAN", false, "false"), + _all("-all", "Show all columns", + "BOOLEAN", false, "false"), + _help("-help", "Show meaning of all the columns", + "BOOLEAN", false, "false"), + _columns("columns", "Comma-separated list of all the columns to show. " + "If not specified, the following columns are shown: " DEFAULT_COLUMNS, + "STRING", false) { + _dcmdparser.add_dcmd_option(&_all); + _dcmdparser.add_dcmd_option(&_csv); + _dcmdparser.add_dcmd_option(&_help); + _dcmdparser.add_dcmd_argument(&_columns); +} + +void ClassStatsDCmd::execute(TRAPS) { + if (!UnlockDiagnosticVMOptions) { + output()->print_cr("GC.class_stats command requires -XX:+UnlockDiagnosticVMOptions"); + return; + } + + VM_GC_HeapInspection heapop(output(), + true, /* request_full_gc */ + true /* need_prologue */); + heapop.set_csv_format(_csv.value()); + heapop.set_print_help(_help.value()); + heapop.set_print_class_stats(true); + if (_all.value()) { + if (_columns.has_value()) { + output()->print_cr("Cannot specify -all and individual columns at the same time"); + return; + } else { + heapop.set_columns(NULL); + } + } else { + if (_columns.has_value()) { + heapop.set_columns(_columns.value()); + } else { + heapop.set_columns(DEFAULT_COLUMNS); + } + } + VMThread::execute(&heapop); +} + +int ClassStatsDCmd::num_arguments() { + ResourceMark rm; + ClassStatsDCmd* dcmd = new ClassStatsDCmd(NULL, false); + if (dcmd != NULL) { + DCmdMark mark(dcmd); + return dcmd->_dcmdparser.num_arguments(); + } else { + return 0; + } +} +#endif // INCLUDE_SERVICES + ThreadDumpDCmd::ThreadDumpDCmd(outputStream* output, bool heap) : DCmdWithParser(output, heap), _locks("-l", "print java.util.concurrent locks", "BOOLEAN", false, "false") { @@ -406,7 +465,32 @@ _jmxremote_ssl_config_file ("jmxremote.ssl.config.file", - "set com.sun.management.jmxremote.ssl_config_file", "STRING", false) + "set com.sun.management.jmxremote.ssl_config_file", "STRING", false), + +// JDP Protocol support + _jmxremote_autodiscovery + ("jmxremote.autodiscovery", + "set com.sun.management.jmxremote.autodiscovery", "STRING", false), + + _jdp_port + ("jdp.port", + "set com.sun.management.jdp.port", "INT", false), + + _jdp_address + ("jdp.address", + "set com.sun.management.jdp.address", "STRING", false), + + _jdp_source_addr + ("jdp.source_addr", + "set com.sun.management.jdp.source_addr", "STRING", false), + + _jdp_ttl + ("jdp.ttl", + "set com.sun.management.jdp.ttl", "INT", false), + + _jdp_pause + ("jdp.pause", + "set com.sun.management.jdp.pause", "INT", false) { _dcmdparser.add_dcmd_option(&_config_file); @@ -422,6 +506,12 @@ _dcmdparser.add_dcmd_option(&_jmxremote_ssl_enabled_protocols); _dcmdparser.add_dcmd_option(&_jmxremote_ssl_need_client_auth); _dcmdparser.add_dcmd_option(&_jmxremote_ssl_config_file); + _dcmdparser.add_dcmd_option(&_jmxremote_autodiscovery); + _dcmdparser.add_dcmd_option(&_jdp_port); + _dcmdparser.add_dcmd_option(&_jdp_address); + _dcmdparser.add_dcmd_option(&_jdp_source_addr); + _dcmdparser.add_dcmd_option(&_jdp_ttl); + _dcmdparser.add_dcmd_option(&_jdp_pause); } @@ -436,7 +526,6 @@ } } - void JMXStartRemoteDCmd::execute(TRAPS) { ResourceMark rm(THREAD); HandleMark hm(THREAD); @@ -466,7 +555,9 @@ // file. #define PUT_OPTION(a) \ if ( (a).is_set() ){ \ - options.print("%scom.sun.management.%s=%s", comma, (a).name(), (a).value()); \ + options.print(\ + ( *((a).type()) == 'I' ) ? "%scom.sun.management.%s=%d" : "%scom.sun.management.%s=%s",\ + comma, (a).name(), (a).value()); \ comma[0] = ','; \ } @@ -483,6 +574,12 @@ PUT_OPTION(_jmxremote_ssl_enabled_protocols); PUT_OPTION(_jmxremote_ssl_need_client_auth); PUT_OPTION(_jmxremote_ssl_config_file); + PUT_OPTION(_jmxremote_autodiscovery); + PUT_OPTION(_jdp_port); + PUT_OPTION(_jdp_address); + PUT_OPTION(_jdp_source_addr); + PUT_OPTION(_jdp_ttl); + PUT_OPTION(_jdp_pause); #undef PUT_OPTION diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/services/diagnosticCommand.hpp --- a/src/share/vm/services/diagnosticCommand.hpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/services/diagnosticCommand.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,6 +35,7 @@ #include "services/diagnosticCommand.hpp" #include "services/diagnosticFramework.hpp" #include "services/diagnosticCommand_ext.hpp" +#include "utilities/macros.hpp" class HelpDCmd : public DCmdWithParser { protected: @@ -178,7 +179,7 @@ }; #endif // INCLUDE_SERVICES -// See also: inspeactheap in attachListener.cpp +// See also: inspectheap in attachListener.cpp class ClassHistogramDCmd : public DCmdWithParser { protected: DCmdArgument _all; @@ -197,6 +198,27 @@ virtual void execute(TRAPS); }; +class ClassStatsDCmd : public DCmdWithParser { +protected: + DCmdArgument _all; + DCmdArgument _csv; + DCmdArgument _help; + DCmdArgument _columns; +public: + ClassStatsDCmd(outputStream* output, bool heap); + static const char* name() { + return "GC.class_stats"; + } + static const char* description() { + return "Provide statistics about Java class meta data. Requires -XX:+UnlockDiagnosticVMOptions."; + } + static const char* impact() { + return "High: Depends on Java heap size and content."; + } + static int num_arguments(); + virtual void execute(TRAPS); +}; + // See also: thread_dump in attachListener.cpp class ThreadDumpDCmd : public DCmdWithParser { protected: @@ -236,6 +258,16 @@ DCmdArgument _jmxremote_ssl_need_client_auth; DCmdArgument _jmxremote_ssl_config_file; + // JDP support + // Keep autodiscovery char* not bool to pass true/false + // as property value to java level. + DCmdArgument _jmxremote_autodiscovery; + DCmdArgument _jdp_port; + DCmdArgument _jdp_address; + DCmdArgument _jdp_source_addr; + DCmdArgument _jdp_ttl; + DCmdArgument _jdp_pause; + public: JMXStartRemoteDCmd(outputStream *output, bool heap_allocated); diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/services/g1MemoryPool.hpp --- a/src/share/vm/services/g1MemoryPool.hpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/services/g1MemoryPool.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -25,11 +25,12 @@ #ifndef SHARE_VM_SERVICES_G1MEMORYPOOL_HPP #define SHARE_VM_SERVICES_G1MEMORYPOOL_HPP -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/g1/g1MonitoringSupport.hpp" #include "services/memoryPool.hpp" #include "services/memoryUsage.hpp" -#endif +#endif // INCLUDE_ALL_GCS // This file contains the three classes that represent the memory // pools of the G1 spaces: G1EdenPool, G1SurvivorPool, and diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/services/heapDumper.cpp --- a/src/share/vm/services/heapDumper.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/services/heapDumper.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -40,9 +40,10 @@ #include "services/heapDumper.hpp" #include "services/threadService.hpp" #include "utilities/ostream.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/parallelScavenge/parallelScavengeHeap.hpp" -#endif +#endif // INCLUDE_ALL_GCS /* * HPROF binary format - description copied from: diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/services/management.cpp --- a/src/share/vm/services/management.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/services/management.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -53,6 +53,7 @@ #include "services/memoryService.hpp" #include "services/runtimeService.hpp" #include "services/threadService.hpp" +#include "utilities/macros.hpp" PerfVariable* Management::_begin_vm_creation_time = NULL; PerfVariable* Management::_end_vm_creation_time = NULL; diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/services/memBaseline.cpp --- a/src/share/vm/services/memBaseline.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/services/memBaseline.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -40,6 +40,7 @@ {mtNMT, "Memory Tracking"}, {mtChunk, "Pooled Free Chunks"}, {mtClassShared,"Shared spaces for classes"}, + {mtTest, "Test"}, {mtNone, "Unknown"} // It can happen when type tagging records are lagging // behind }; diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/services/memPtr.cpp --- a/src/share/vm/services/memPtr.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/services/memPtr.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -27,8 +27,8 @@ #include "services/memTracker.hpp" volatile jint SequenceGenerator::_seq_number = 1; +volatile unsigned long SequenceGenerator::_generation = 1; NOT_PRODUCT(jint SequenceGenerator::_max_seq_number = 1;) -DEBUG_ONLY(volatile unsigned long SequenceGenerator::_generation = 0;) jint SequenceGenerator::next() { jint seq = Atomic::add(1, &_seq_number); diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/services/memPtr.hpp --- a/src/share/vm/services/memPtr.hpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/services/memPtr.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -47,16 +47,16 @@ static void reset() { assert(SafepointSynchronize::is_at_safepoint(), "Safepoint required"); _seq_number = 1; - DEBUG_ONLY(_generation ++;) + _generation ++; }; - DEBUG_ONLY(static unsigned long current_generation() { return (unsigned long)_generation; }) + static unsigned long current_generation() { return _generation; } NOT_PRODUCT(static jint max_seq_num() { return _max_seq_number; }) private: - static volatile jint _seq_number; - NOT_PRODUCT(static jint _max_seq_number; ) - DEBUG_ONLY(static volatile unsigned long _generation; ) + static volatile jint _seq_number; + static volatile unsigned long _generation; + NOT_PRODUCT(static jint _max_seq_number; ) }; /* diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/services/memRecorder.cpp --- a/src/share/vm/services/memRecorder.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/services/memRecorder.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -55,7 +55,7 @@ MemRecorder::MemRecorder() { assert(MemTracker::is_on(), "Native memory tracking is off"); Atomic::inc(&_instance_count); - debug_only(set_generation();) + set_generation(); if (MemTracker::track_callsite()) { _pointer_records = new (std::nothrow)FixedSizeMemPointerArrayis_arena_record()) { MemPointerRecord* next = (MemPointerRecord*)malloc_snapshot_itr.peek_next(); - if (next->is_arena_memory_record() && next->is_memory_record_of_arena(matched_rec)) { + if (next != NULL && next->is_arena_memory_record() && + next->is_memory_record_of_arena(matched_rec)) { malloc_snapshot_itr.remove(); } } diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/services/memTrackWorker.cpp --- a/src/share/vm/services/memTrackWorker.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/services/memTrackWorker.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -91,6 +91,8 @@ MemSnapshot* snapshot = MemTracker::get_snapshot(); assert(snapshot != NULL, "Worker should not be started"); MemRecorder* rec; + unsigned long processing_generation = 0; + bool worker_idle = false; while (!MemTracker::shutdown_in_progress()) { NOT_PRODUCT(_last_gen_in_use = generations_in_use();) @@ -100,6 +102,12 @@ rec = _gen[_head].next_recorder(); } if (rec != NULL) { + if (rec->get_generation() != processing_generation || worker_idle) { + processing_generation = rec->get_generation(); + worker_idle = false; + MemTracker::set_current_processing_generation(processing_generation); + } + // merge the recorder into staging area if (!snapshot->merge(rec)) { MemTracker::shutdown(MemTracker::NMT_out_of_memory); @@ -129,6 +137,9 @@ MemTracker::shutdown(MemTracker::NMT_out_of_memory); } } else { + // worker thread is idle + worker_idle = true; + MemTracker::report_worker_idle(); snapshot->wait(1000); ThreadCritical tc; // check if more data arrived diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/services/memTrackWorker.hpp --- a/src/share/vm/services/memTrackWorker.hpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/services/memTrackWorker.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -107,6 +107,7 @@ NOT_PRODUCT(int _merge_count;) NOT_PRODUCT(int _last_gen_in_use;) + // how many generations are queued inline int generations_in_use() const { return (_tail >= _head ? (_tail - _head + 1) : (MAX_GENERATIONS - (_head - _tail) + 1)); } diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/services/memTracker.cpp --- a/src/share/vm/services/memTracker.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/services/memTracker.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -29,6 +29,7 @@ #include "runtime/mutexLocker.hpp" #include "runtime/safepoint.hpp" #include "runtime/threadCritical.hpp" +#include "runtime/vm_operations.hpp" #include "services/memPtr.hpp" #include "services/memReporter.hpp" #include "services/memTracker.hpp" @@ -65,6 +66,8 @@ MemTracker::ShutdownReason MemTracker::_reason = NMT_shutdown_none; int MemTracker::_thread_count = 255; volatile jint MemTracker::_pooled_recorder_count = 0; +volatile unsigned long MemTracker::_processing_generation = 0; +volatile bool MemTracker::_worker_thread_idle = false; debug_only(intx MemTracker::_main_thread_tid = 0;) NOT_PRODUCT(volatile jint MemTracker::_pending_recorder_count = 0;) @@ -279,7 +282,7 @@ } cur_head->set_next(NULL); Atomic::dec(&_pooled_recorder_count); - debug_only(cur_head->set_generation();) + cur_head->set_generation(); return cur_head; } } @@ -570,6 +573,51 @@ return false; } +// Whitebox API for blocking until the current generation of NMT data has been merged +bool MemTracker::wbtest_wait_for_data_merge() { + // NMT can't be shutdown while we're holding _query_lock + MutexLockerEx lock(_query_lock, true); + assert(_worker_thread != NULL, "Invalid query"); + // the generation at query time, so NMT will spin till this generation is processed + unsigned long generation_at_query_time = SequenceGenerator::current_generation(); + unsigned long current_processing_generation = _processing_generation; + // if generation counter overflown + bool generation_overflown = (generation_at_query_time < current_processing_generation); + long generations_to_wrap = MAX_UNSIGNED_LONG - current_processing_generation; + // spin + while (!shutdown_in_progress()) { + if (!generation_overflown) { + if (current_processing_generation > generation_at_query_time) { + return true; + } + } else { + assert(generations_to_wrap >= 0, "Sanity check"); + long current_generations_to_wrap = MAX_UNSIGNED_LONG - current_processing_generation; + assert(current_generations_to_wrap >= 0, "Sanity check"); + // to overflow an unsigned long should take long time, so to_wrap check should be sufficient + if (current_generations_to_wrap > generations_to_wrap && + current_processing_generation > generation_at_query_time) { + return true; + } + } + + // if worker thread is idle, but generation is not advancing, that means + // there is not safepoint to let NMT advance generation, force one. + if (_worker_thread_idle) { + VM_ForceSafepoint vfs; + VMThread::execute(&vfs); + } + MemSnapshot* snapshot = get_snapshot(); + if (snapshot == NULL) { + return false; + } + snapshot->wait(1000); + current_processing_generation = _processing_generation; + } + // We end up here if NMT is shutting down before our data has been merged + return false; +} + // compare memory usage between current snapshot and baseline bool MemTracker::compare_memory_usage(BaselineOutputer& out, size_t unit, bool summary_only) { MutexLockerEx lock(_query_lock, true); diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/services/memTracker.hpp --- a/src/share/vm/services/memTracker.hpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/services/memTracker.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -91,9 +91,10 @@ static bool compare_memory_usage(BaselineOutputer& out, size_t unit, bool summary_only = true) { } + static bool wbtest_wait_for_data_merge() { } + static inline void sync() { } static inline void thread_exiting(JavaThread* thread) { } - }; @@ -111,6 +112,10 @@ extern bool NMT_track_callsite; +#ifndef MAX_UNSIGNED_LONG +#define MAX_UNSIGNED_LONG (unsigned long)(-1) +#endif + #ifdef ASSERT #define DEBUG_CALLER_PC (NMT_track_callsite ? os::get_caller_pc(2) : 0) #else @@ -380,6 +385,11 @@ static bool compare_memory_usage(BaselineOutputer& out, size_t unit, bool summary_only = true); + // the version for whitebox testing support, it ensures that all memory + // activities before this method call, are reflected in the snapshot + // database. + static bool wbtest_wait_for_data_merge(); + // sync is called within global safepoint to synchronize nmt data static void sync(); @@ -432,6 +442,15 @@ static void create_record_in_recorder(address addr, MEMFLAGS type, size_t size, address pc, JavaThread* thread); + static void set_current_processing_generation(unsigned long generation) { + _worker_thread_idle = false; + _processing_generation = generation; + } + + static void report_worker_idle() { + _worker_thread_idle = true; + } + private: // global memory snapshot static MemSnapshot* _snapshot; @@ -483,6 +502,11 @@ static volatile enum NMTStates _state; // the reason for shutting down nmt static enum ShutdownReason _reason; + // the generation that NMT is processing + static volatile unsigned long _processing_generation; + // although NMT is still procesing current generation, but + // there is not more recorder to process, set idle state + static volatile bool _worker_thread_idle; }; #endif // !INCLUDE_NMT diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/services/memoryPool.cpp --- a/src/share/vm/services/memoryPool.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/services/memoryPool.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -32,6 +32,7 @@ #include "services/management.hpp" #include "services/memoryManager.hpp" #include "services/memoryPool.hpp" +#include "utilities/macros.hpp" MemoryPool::MemoryPool(const char* name, PoolType type, @@ -208,7 +209,7 @@ return MemoryUsage(initial_size(), used, committed, maxSize); } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS CompactibleFreeListSpacePool::CompactibleFreeListSpacePool(CompactibleFreeListSpace* space, const char* name, PoolType type, @@ -225,7 +226,7 @@ return MemoryUsage(initial_size(), used, committed, maxSize); } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS GenerationPool::GenerationPool(Generation* gen, const char* name, diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/services/memoryPool.hpp --- a/src/share/vm/services/memoryPool.hpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/services/memoryPool.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -30,9 +30,10 @@ #include "memory/heap.hpp" #include "memory/space.hpp" #include "services/memoryUsage.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp" -#endif +#endif // INCLUDE_ALL_GCS // A memory pool represents the memory area that the VM manages. // The Java virtual machine has at least one memory pool @@ -185,7 +186,7 @@ } }; -#ifndef SERIALGC +#if INCLUDE_ALL_GCS class CompactibleFreeListSpacePool : public CollectedMemoryPool { private: CompactibleFreeListSpace* _space; @@ -199,7 +200,7 @@ MemoryUsage get_memory_usage(); size_t used_in_bytes() { return _space->used(); } }; -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS class GenerationPool : public CollectedMemoryPool { diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/services/memoryService.cpp --- a/src/share/vm/services/memoryService.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/services/memoryService.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -43,7 +43,8 @@ #include "services/memoryPool.hpp" #include "services/memoryService.hpp" #include "utilities/growableArray.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp" #include "gc_implementation/g1/g1CollectedHeap.inline.hpp" #include "gc_implementation/parNew/parNewGeneration.hpp" @@ -52,7 +53,7 @@ #include "gc_implementation/parallelScavenge/psYoungGen.hpp" #include "services/g1MemoryPool.hpp" #include "services/psMemoryPool.hpp" -#endif +#endif // INCLUDE_ALL_GCS GrowableArray* MemoryService::_pools_list = new (ResourceObj::C_HEAP, mtInternal) GrowableArray(init_pools_list_size, true); @@ -83,7 +84,7 @@ add_gen_collected_heap_info(GenCollectedHeap::heap()); break; } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS case CollectedHeap::ParallelScavengeHeap : { add_parallel_scavenge_heap_info(ParallelScavengeHeap::heap()); break; @@ -92,7 +93,7 @@ add_g1_heap_info(G1CollectedHeap::heap()); break; } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS default: { guarantee(false, "Unrecognized kind of heap"); } @@ -130,22 +131,22 @@ case Generation::DefNew: _minor_gc_manager = MemoryManager::get_copy_memory_manager(); break; -#ifndef SERIALGC +#if INCLUDE_ALL_GCS case Generation::ParNew: case Generation::ASParNew: _minor_gc_manager = MemoryManager::get_parnew_memory_manager(); break; -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS default: guarantee(false, "Unrecognized generation spec"); break; } if (policy->is_mark_sweep_policy()) { _major_gc_manager = MemoryManager::get_msc_memory_manager(); -#ifndef SERIALGC +#if INCLUDE_ALL_GCS } else if (policy->is_concurrent_mark_sweep_policy()) { _major_gc_manager = MemoryManager::get_cms_memory_manager(); -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS } else { guarantee(false, "Unknown two-gen policy"); } @@ -159,7 +160,7 @@ add_generation_memory_pool(heap->get_gen(major), _major_gc_manager); } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS // Add memory pools for ParallelScavengeHeap // This function currently only supports two generations collected heap. // The collector for ParallelScavengeHeap will have two memory managers. @@ -185,7 +186,7 @@ add_g1YoungGen_memory_pool(g1h, _major_gc_manager, _minor_gc_manager); add_g1OldGen_memory_pool(g1h, _major_gc_manager); } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS MemoryPool* MemoryService::add_gen(Generation* gen, const char* name, @@ -222,7 +223,7 @@ return (MemoryPool*) pool; } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS MemoryPool* MemoryService::add_cms_space(CompactibleFreeListSpace* space, const char* name, bool is_heap, @@ -233,7 +234,7 @@ _pools_list->append(pool); return (MemoryPool*) pool; } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS // Add memory pool(s) for one generation void MemoryService::add_generation_memory_pool(Generation* gen, @@ -261,7 +262,7 @@ break; } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS case Generation::ParNew: case Generation::ASParNew: { @@ -282,7 +283,7 @@ break; } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS case Generation::MarkSweepCompact: { assert(major_mgr != NULL && minor_mgr == NULL, "Should have only one manager"); @@ -293,7 +294,7 @@ break; } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS case Generation::ConcurrentMarkSweep: case Generation::ASConcurrentMarkSweep: { @@ -306,7 +307,7 @@ true /* support_usage_threshold */); break; } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS default: assert(false, "should not reach here"); @@ -326,7 +327,7 @@ } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS void MemoryService::add_psYoung_memory_pool(PSYoungGen* gen, MemoryManager* major_mgr, MemoryManager* minor_mgr) { assert(major_mgr != NULL && minor_mgr != NULL, "Should have two managers"); @@ -384,7 +385,7 @@ mgr->add_pool(old_gen); _pools_list->append(old_gen); } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS void MemoryService::add_code_heap_memory_pool(CodeHeap* heap) { _code_heap_pool = new CodeHeapPool(heap, @@ -534,17 +535,17 @@ TraceMemoryManagerStats::TraceMemoryManagerStats(Generation::Name kind, GCCause::Cause cause) { switch (kind) { case Generation::DefNew: -#ifndef SERIALGC +#if INCLUDE_ALL_GCS case Generation::ParNew: case Generation::ASParNew: -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS _fullGC=false; break; case Generation::MarkSweepCompact: -#ifndef SERIALGC +#if INCLUDE_ALL_GCS case Generation::ConcurrentMarkSweep: case Generation::ASConcurrentMarkSweep: -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS _fullGC=true; break; default: diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/services/psMemoryPool.hpp --- a/src/share/vm/services/psMemoryPool.hpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/services/psMemoryPool.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -25,7 +25,8 @@ #ifndef SHARE_VM_SERVICES_PSMEMORYPOOL_HPP #define SHARE_VM_SERVICES_PSMEMORYPOOL_HPP -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "gc_implementation/parallelScavenge/psOldGen.hpp" #include "gc_implementation/parallelScavenge/psYoungGen.hpp" #include "gc_implementation/shared/mutableSpace.hpp" @@ -34,7 +35,7 @@ #include "memory/space.hpp" #include "services/memoryPool.hpp" #include "services/memoryUsage.hpp" -#endif +#endif // INCLUDE_ALL_GCS class PSGenerationPool : public CollectedMemoryPool { private: diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/services/runtimeService.cpp --- a/src/share/vm/services/runtimeService.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/services/runtimeService.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -29,6 +29,7 @@ #include "services/runtimeService.hpp" #include "utilities/dtrace.hpp" #include "utilities/exceptions.hpp" +#include "utilities/macros.hpp" #ifndef USDT2 HS_DTRACE_PROBE_DECL(hs_private, safepoint__begin); diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/utilities/accessFlags.cpp --- a/src/share/vm/utilities/accessFlags.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/utilities/accessFlags.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -59,7 +59,7 @@ } while(f != old_flags); } -#ifndef PRODUCT +#if !defined(PRODUCT) || INCLUDE_JVMTI void AccessFlags::print_on(outputStream* st) const { if (is_public ()) st->print("public " ); @@ -80,7 +80,7 @@ if (on_stack ()) st->print("{on_stack} " ); } -#endif +#endif // !PRODUCT || INCLUDE_JVMTI void accessFlags_init() { assert(sizeof(AccessFlags) == sizeof(jint), "just checking size of flags"); diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/utilities/accessFlags.hpp --- a/src/share/vm/utilities/accessFlags.hpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/utilities/accessFlags.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -239,7 +239,11 @@ inline friend AccessFlags accessFlags_from(jint flags); // Printing/debugging +#if INCLUDE_JVMTI + void print_on(outputStream* st) const; +#else void print_on(outputStream* st) const PRODUCT_RETURN; +#endif }; inline AccessFlags accessFlags_from(jint flags) { diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/utilities/constantTag.cpp --- a/src/share/vm/utilities/constantTag.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/utilities/constantTag.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -52,7 +52,6 @@ case JVM_CONSTANT_StringIndex : case JVM_CONSTANT_MethodHandle : case JVM_CONSTANT_MethodType : - case JVM_CONSTANT_Object : return T_OBJECT; default: ShouldNotReachHere(); @@ -96,8 +95,6 @@ return "MethodType Error"; case JVM_CONSTANT_InvokeDynamic : return "InvokeDynamic"; - case JVM_CONSTANT_Object : - return "Object"; case JVM_CONSTANT_Utf8 : return "Utf8"; case JVM_CONSTANT_UnresolvedClass : diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/utilities/constantTag.hpp --- a/src/share/vm/utilities/constantTag.hpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/utilities/constantTag.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -43,8 +43,7 @@ JVM_CONSTANT_UnresolvedClassInError = 103, // Error tag due to resolution error JVM_CONSTANT_MethodHandleInError = 104, // Error tag due to resolution error JVM_CONSTANT_MethodTypeInError = 105, // Error tag due to resolution error - JVM_CONSTANT_Object = 106, // Required for BoundMethodHandle arguments. - JVM_CONSTANT_InternalMax = 106 // Last implementation tag + JVM_CONSTANT_InternalMax = 105 // Last implementation tag }; @@ -84,8 +83,6 @@ bool is_klass_index() const { return _tag == JVM_CONSTANT_ClassIndex; } bool is_string_index() const { return _tag == JVM_CONSTANT_StringIndex; } - bool is_object() const { return _tag == JVM_CONSTANT_Object; } - bool is_klass_reference() const { return is_klass_index() || is_unresolved_klass(); } bool is_klass_or_reference() const{ return is_klass() || is_klass_reference(); } bool is_field_or_method() const { return is_field() || is_method() || is_interface_method(); } @@ -98,7 +95,7 @@ bool is_loadable_constant() const { return ((_tag >= JVM_CONSTANT_Integer && _tag <= JVM_CONSTANT_String) || is_method_type() || is_method_handle() || - is_unresolved_klass() || is_object()); + is_unresolved_klass()); } constantTag() { diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/utilities/debug.cpp --- a/src/share/vm/utilities/debug.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/utilities/debug.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -228,28 +228,16 @@ report_vm_error(file, line, "fatal error", message); } -// Used by report_vm_out_of_memory to detect recursion. -static jint _exiting_out_of_mem = 0; - void report_vm_out_of_memory(const char* file, int line, size_t size, const char* message) { if (Debugging) return; - // We try to gather additional information for the first out of memory - // error only; gathering additional data might cause an allocation and a - // recursive out_of_memory condition. - - const jint exiting = 1; - // If we succeed in changing the value, we're the first one in. - bool first_time_here = Atomic::xchg(exiting, &_exiting_out_of_mem) != exiting; + Thread* thread = ThreadLocalStorage::get_thread_slow(); + VMError(thread, file, line, size, message).report_and_die(); - if (first_time_here) { - Thread* thread = ThreadLocalStorage::get_thread_slow(); - VMError(thread, file, line, size, message).report_and_die(); - } - - // Dump core and abort - vm_abort(true); + // The UseOSErrorReporting option in report_and_die() may allow a return + // to here. If so then we'll have to figure out how to handle it. + guarantee(false, "report_and_die() should not return here"); } void report_should_not_call(const char* file, int line) { diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/utilities/macros.hpp --- a/src/share/vm/utilities/macros.hpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/utilities/macros.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -130,23 +130,23 @@ #endif // INCLUDE_MANAGEMENT /* - * When INCLUDE_ALTERNATE_GCS is false the only garbage collectors + * When INCLUDE_ALL_GCS is false the only garbage collectors * included in the JVM are defaultNewGeneration and markCompact. * - * When INCLUDE_ALTERNATE_GCS is true all garbage collectors are + * When INCLUDE_ALL_GCS is true all garbage collectors are * included in the JVM. */ -#ifndef INCLUDE_ALTERNATE_GCS -#define INCLUDE_ALTERNATE_GCS 1 -#endif // INCLUDE_ALTERNATE_GCS +#ifndef INCLUDE_ALL_GCS +#define INCLUDE_ALL_GCS 1 +#endif // INCLUDE_ALL_GCS -#if INCLUDE_ALTERNATE_GCS -#define NOT_ALTERNATE_GCS_RETURN /* next token must be ; */ -#define NOT_ALTERNATE_GCS_RETURN_(code) /* next token must be ; */ +#if INCLUDE_ALL_GCS +#define NOT_ALL_GCS_RETURN /* next token must be ; */ +#define NOT_ALL_GCS_RETURN_(code) /* next token must be ; */ #else -#define NOT_ALTERNATE_GCS_RETURN {} -#define NOT_ALTERNATE_GCS_RETURN_(code) { return code; } -#endif // INCLUDE_ALTERNATE_GCS +#define NOT_ALL_GCS_RETURN {} +#define NOT_ALL_GCS_RETURN_(code) { return code; } +#endif // INCLUDE_ALL_GCS #ifndef INCLUDE_NMT #define INCLUDE_NMT 1 diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/utilities/ostream.cpp --- a/src/share/vm/utilities/ostream.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/utilities/ostream.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -432,7 +432,7 @@ rotatingFileStream::rotatingFileStream(const char* file_name) { _cur_file_num = 0; - _bytes_writen = 0L; + _bytes_written = 0L; _file_name = NEW_C_HEAP_ARRAY(char, strlen(file_name)+10, mtInternal); jio_snprintf(_file_name, strlen(file_name)+10, "%s.%d", file_name, _cur_file_num); _file = fopen(_file_name, "w"); @@ -441,7 +441,7 @@ rotatingFileStream::rotatingFileStream(const char* file_name, const char* opentype) { _cur_file_num = 0; - _bytes_writen = 0L; + _bytes_written = 0L; _file_name = NEW_C_HEAP_ARRAY(char, strlen(file_name)+10, mtInternal); jio_snprintf(_file_name, strlen(file_name)+10, "%s.%d", file_name, _cur_file_num); _file = fopen(_file_name, opentype); @@ -449,10 +449,9 @@ } void rotatingFileStream::write(const char* s, size_t len) { - if (_file != NULL) { - // Make an unused local variable to avoid warning from gcc 4.x compiler. + if (_file != NULL) { size_t count = fwrite(s, 1, len, _file); - Atomic::add((jlong)count, &_bytes_writen); + _bytes_written += count; } update_position(s, len); } @@ -466,7 +465,10 @@ // concurrent GC threads to run parallel with VMThread at safepoint, write and rotate_log // must be synchronized. void rotatingFileStream::rotate_log() { - if (_bytes_writen < (jlong)GCLogFileSize) return; + if (_bytes_written < (jlong)GCLogFileSize) { + return; + } + #ifdef ASSERT Thread *thread = Thread::current(); assert(thread == NULL || @@ -476,7 +478,7 @@ if (NumberOfGCLogFiles == 1) { // rotate in same file rewind(); - _bytes_writen = 0L; + _bytes_written = 0L; return; } @@ -492,7 +494,7 @@ } _file = fopen(_file_name, "w"); if (_file != NULL) { - _bytes_writen = 0L; + _bytes_written = 0L; _need_close = true; } else { tty->print_cr("failed to open rotation log file %s due to %s\n", diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/utilities/ostream.hpp --- a/src/share/vm/utilities/ostream.hpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/utilities/ostream.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -231,7 +231,7 @@ class rotatingFileStream : public fileStream { protected: char* _file_name; - jlong _bytes_writen; + jlong _bytes_written; uintx _cur_file_num; // current logfile rotation number, from 0 to MaxGCLogFileNumbers-1 public: rotatingFileStream(const char* file_name); diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/utilities/top.hpp --- a/src/share/vm/utilities/top.hpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/utilities/top.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -33,9 +33,9 @@ #include "utilities/macros.hpp" #include "utilities/ostream.hpp" #include "utilities/sizes.hpp" -#ifndef SERIALGC +#if INCLUDE_ALL_GCS #include "gc_implementation/g1/g1_globals.hpp" -#endif +#endif // INCLUDE_ALL_GCS #ifdef COMPILER1 #include "c1/c1_globals.hpp" #endif diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/utilities/vmError.cpp diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/utilities/yieldingWorkgroup.cpp --- a/src/share/vm/utilities/yieldingWorkgroup.cpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/utilities/yieldingWorkgroup.cpp Tue Mar 05 23:44:54 2013 +0100 @@ -23,9 +23,8 @@ */ #include "precompiled.hpp" -#ifndef SERIALGC +#include "utilities/macros.hpp" #include "utilities/yieldingWorkgroup.hpp" -#endif // Forward declaration of classes declared here. diff -r a413bcd552a4 -r 5fc51c1ecdeb src/share/vm/utilities/yieldingWorkgroup.hpp --- a/src/share/vm/utilities/yieldingWorkgroup.hpp Tue Mar 05 21:58:51 2013 +0100 +++ b/src/share/vm/utilities/yieldingWorkgroup.hpp Tue Mar 05 23:44:54 2013 +0100 @@ -25,9 +25,10 @@ #ifndef SHARE_VM_UTILITIES_YIELDINGWORKGROUP_HPP #define SHARE_VM_UTILITIES_YIELDINGWORKGROUP_HPP -#ifndef SERIALGC +#include "utilities/macros.hpp" +#if INCLUDE_ALL_GCS #include "utilities/workgroup.hpp" -#endif +#endif // INCLUDE_ALL_GCS // Forward declarations diff -r a413bcd552a4 -r 5fc51c1ecdeb test/TEST.ROOT --- a/test/TEST.ROOT Tue Mar 05 21:58:51 2013 +0100 +++ b/test/TEST.ROOT Tue Mar 05 23:44:54 2013 +0100 @@ -28,4 +28,4 @@ # DO NOT EDIT without first contacting hotspot-regtest@sun.com # The list of keywords supported in this test suite -keys=cte_test +keys=cte_test jcmd nmt regression gc diff -r a413bcd552a4 -r 5fc51c1ecdeb test/compiler/5091921/Test6850611.java --- a/test/compiler/5091921/Test6850611.java Tue Mar 05 21:58:51 2013 +0100 +++ b/test/compiler/5091921/Test6850611.java Tue Mar 05 23:44:54 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,7 +27,7 @@ * @bug 6850611 * @summary int / long arithmetic seems to be broken in 1.6.0_14 HotSpot Server VM (Win XP) * - * @run main Test6850611 + * @run main/timeout=480 Test6850611 */ public class Test6850611 { diff -r a413bcd552a4 -r 5fc51c1ecdeb test/compiler/5091921/Test6890943.java --- a/test/compiler/5091921/Test6890943.java Tue Mar 05 21:58:51 2013 +0100 +++ b/test/compiler/5091921/Test6890943.java Tue Mar 05 23:44:54 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,7 +27,7 @@ * @bug 6890943 * @summary JVM mysteriously gives wrong result on 64-bit 1.6 VMs in hotspot mode. * - * @run shell Test6890943.sh + * @run shell/timeout=240 Test6890943.sh */ import java.util.*; import java.io.*; diff -r a413bcd552a4 -r 5fc51c1ecdeb test/compiler/5091921/Test6890943.sh --- a/test/compiler/5091921/Test6890943.sh Tue Mar 05 21:58:51 2013 +0100 +++ b/test/compiler/5091921/Test6890943.sh Tue Mar 05 23:44:54 2013 +0100 @@ -1,6 +1,6 @@ #!/bin/sh # -# Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -52,7 +52,10 @@ ${TESTJAVA}/bin/javac -d . Test6890943.java -${TESTJAVA}/bin/java -XX:-PrintVMOptions ${TESTVMOPTS} Test6890943 < input6890943.txt > test.out 2>&1 +${TESTJAVA}/bin/java -XX:-PrintVMOptions -XX:+IgnoreUnrecognizedVMOptions ${TESTVMOPTS} Test6890943 < input6890943.txt > pretest.out 2>&1 + +# This test sometimes tickles an unrelated performance warning that interferes with diff. +grep -v 'warning: Performance bug: SystemDictionary' pretest.out > test.out diff output6890943.txt test.out diff -r a413bcd552a4 -r 5fc51c1ecdeb test/compiler/5091921/Test6905845.java --- a/test/compiler/5091921/Test6905845.java Tue Mar 05 21:58:51 2013 +0100 +++ b/test/compiler/5091921/Test6905845.java Tue Mar 05 23:44:54 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,7 +27,7 @@ * @bug 6905845 * @summary Server VM improperly optimizing away loop. * - * @run main Test6905845 + * @run main/timeout=480 Test6905845 */ public class Test6905845 { diff -r a413bcd552a4 -r 5fc51c1ecdeb test/compiler/5091921/Test6992759.java --- a/test/compiler/5091921/Test6992759.java Tue Mar 05 21:58:51 2013 +0100 +++ b/test/compiler/5091921/Test6992759.java Tue Mar 05 23:44:54 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,7 +27,7 @@ * @bug 6992759 * @summary Bad code generated for integer <= comparison, fails for Integer.MAX_VALUE * - * @run main Test6992759 + * @run main/timeout=240 Test6992759 */ public class Test6992759 { diff -r a413bcd552a4 -r 5fc51c1ecdeb test/compiler/6852078/Test6852078.java --- a/test/compiler/6852078/Test6852078.java Tue Mar 05 21:58:51 2013 +0100 +++ b/test/compiler/6852078/Test6852078.java Tue Mar 05 23:44:54 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,7 +27,7 @@ * @bug 6852078 * @summary Disable SuperWord optimization for unsafe read/write * - * @run main/othervm Test6852078 + * @run main Test6852078 */ import java.util.*; @@ -50,7 +50,11 @@ } public static void main(String [] args) { + long start = System.currentTimeMillis(); for (int i=0; i<2000; i++) { + // To protect slow systems from test-too-long timeouts + if ((i > 100) && ((System.currentTimeMillis() - start) > 100000)) + break; Test6852078 t = new Test6852078(args); } } diff -r a413bcd552a4 -r 5fc51c1ecdeb test/compiler/7009359/Test7009359.java --- a/test/compiler/7009359/Test7009359.java Tue Mar 05 21:58:51 2013 +0100 +++ b/test/compiler/7009359/Test7009359.java Tue Mar 05 23:44:54 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,13 +27,13 @@ * @bug 7009359 * @summary HS with -XX:+AggressiveOpts optimize new StringBuffer(null) so it does not throw NPE as expected * - * @run main/othervm -Xbatch -XX:+IgnoreUnrecognizedVMOptions -XX:+OptimizeStringConcat -XX:CompileCommand=exclude,Test7009359,main Test7009359 + * @run main/othervm -Xbatch -XX:+IgnoreUnrecognizedVMOptions -XX:+OptimizeStringConcat -XX:CompileCommand=dontinline,Test7009359,stringmakerBUG Test7009359 * */ public class Test7009359 { public static void main (String[] args) { - for(int i = 0; i < 1000000; i++) { + for(int i = 0; i < 100000; i++) { if(!stringmakerBUG(null).equals("NPE")) { System.out.println("StringBuffer(null) does not throw NPE"); System.exit(97); diff -r a413bcd552a4 -r 5fc51c1ecdeb test/compiler/8004741/Test8004741.java --- a/test/compiler/8004741/Test8004741.java Tue Mar 05 21:58:51 2013 +0100 +++ b/test/compiler/8004741/Test8004741.java Tue Mar 05 23:44:54 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,70 +25,160 @@ * @test Test8004741.java * @bug 8004741 * @summary Missing compiled exception handle table entry for multidimensional array allocation + * @run main/othervm -Xmx64m -Xbatch -XX:+IgnoreUnrecognizedVMOptions -XX:-TieredCompilation -XX:+StressCompiledExceptionHandlers -XX:+SafepointALot -XX:GuaranteedSafepointInterval=100 Test8004741 * @run main/othervm -Xmx64m -Xbatch -XX:+IgnoreUnrecognizedVMOptions -XX:-TieredCompilation -XX:+StressCompiledExceptionHandlers Test8004741 - * */ import java.util.*; public class Test8004741 extends Thread { + static int passed = 0; + + /** + * Loop forever allocating 2-d arrays. + * Catches and rethrows all exceptions; in the case of ThreadDeath, increments passed. + * Note that passed is incremented here because this is the exception handler with + * the smallest scope; we only want to declare success in the case where it is highly + * likely that the test condition + * (exception in 2-d array alloc interrupted by ThreadDeath) + * actually occurs. + */ static int[][] test(int a, int b) throws Exception { - int[][] ar = null; + int[][] ar; try { ar = new int[a][b]; - } catch (Error e) { - System.out.println("test got Error"); - passed = true; - throw(e); - } catch (Exception e) { - System.out.println("test got Exception"); + } catch (ThreadDeath e) { + System.out.println("test got ThreadDeath"); + passed++; throw(e); } return ar; } - static boolean passed = false; + /* Cookbook wait-notify to track progress of test thread. */ + Object progressLock = new Object(); + private static final int NOT_STARTED = 0; + private static final int RUNNING = 1; + private static final int STOPPING = 2; + + int progressState = NOT_STARTED; - public void run() { - System.out.println("test started"); - try { - while(true) { - test(2,20000); + void toState(int state) { + synchronized (progressLock) { + progressState = state; + progressLock.notify(); + } + } + + void waitFor(int state) { + synchronized (progressLock) { + while (progressState < state) { + try { + progressLock.wait(); + } catch (InterruptedException e) { + e.printStackTrace(); + System.out.println("unexpected InterruptedException"); + fail(); } - } catch (ThreadDeath e) { - System.out.println("test got ThreadDeath"); - passed = true; - } catch (Error e) { - e.printStackTrace(); - System.out.println("test got Error"); - } catch (Exception e) { - e.printStackTrace(); - System.out.println("test got Exception"); + } + if (progressState > state) { + System.out.println("unexpected test state change, expected " + + state + " but saw " + progressState); + fail(); + } + } + } + + /** + * Loops running test until some sort of an exception or error, + * expects to see ThreadDeath. + */ + public void run() { + try { + // Print before state change, so that other thread is most likely + // to see this thread executing calls to test() in a loop. + System.out.println("thread running"); + toState(RUNNING); + while (true) { + // (2,2) (2,10) (2,100) were observed to tickle the bug; + test(2, 100); } + } catch (ThreadDeath e) { + // nothing to say, passing was incremented by the test. + } catch (Throwable e) { + e.printStackTrace(); + System.out.println("unexpected Throwable " + e); + fail(); + } + toState(STOPPING); + } + + /** + * Runs a single trial of the test in a thread. + * No single trial is definitive, since the ThreadDeath + * exception might not land in the tested region of code. + */ + public static void threadTest() throws InterruptedException { + Test8004741 t = new Test8004741(); + t.start(); + t.waitFor(RUNNING); + Thread.sleep(100); + System.out.println("stopping thread"); + t.stop(); + t.waitFor(STOPPING); + t.join(); } public static void main(String[] args) throws Exception { + // Warm up "test" + // t will never be started. for (int n = 0; n < 11000; n++) { - test(2, 20); + test(2, 100); + } + + // Will this sleep help ensure that the compiler is run? + Thread.sleep(500); + passed = 0; + + try { + test(-1, 100); + System.out.println("Missing NegativeArraySizeException #1"); + fail(); + } catch ( java.lang.NegativeArraySizeException e ) { + System.out.println("Saw expected NegativeArraySizeException #1"); } - // First test exception catch - Test8004741 t = new Test8004741(); + try { + test(100, -1); + fail(); + System.out.println("Missing NegativeArraySizeException #2"); + fail(); + } catch ( java.lang.NegativeArraySizeException e ) { + System.out.println("Saw expected NegativeArraySizeException #2"); + } - passed = false; - t.start(); - Thread.sleep(1000); - t.stop(); + /* Test repetitions. If the test succeeds-mostly, it succeeds, + * as long as it does not crash (the outcome if the exception range + * table entry for the array allocation is missing). + */ + int N = 12; + for (int n = 0; n < N; n++) { + threadTest(); + } - Thread.sleep(5000); - t.join(); - if (passed) { + if (passed > N/2) { + System.out.println("Saw " + passed + " out of " + N + " possible ThreadDeath hits"); System.out.println("PASSED"); } else { - System.out.println("FAILED"); - System.exit(97); + System.out.println("Too few ThreadDeath hits; expected at least " + N/2 + + " but saw only " + passed); + fail(); } } + static void fail() { + System.out.println("FAILED"); + System.exit(97); + } }; diff -r a413bcd552a4 -r 5fc51c1ecdeb test/compiler/8004867/TestIntAtomicCAS.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/8004867/TestIntAtomicCAS.java Tue Mar 05 23:44:54 2013 +0100 @@ -0,0 +1,969 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/** + * @test + * @bug 8004867 + * @summary VM crashing with assert "share/vm/opto/node.hpp:357 - assert(i < _max) failed: oob" + * + * @run main/othervm/timeout=300 -Xbatch -XX:+IgnoreUnrecognizedVMOptions -XX:-TieredCompilation -XX:-OptimizeFill TestIntAtomicCAS + * @run main/othervm/timeout=300 -Xbatch -XX:+IgnoreUnrecognizedVMOptions -XX:-TieredCompilation -XX:+OptimizeFill TestIntAtomicCAS + */ + +import java.util.concurrent.atomic.AtomicIntegerArray; + +public class TestIntAtomicCAS { + private static final int ARRLEN = 97; + private static final int ITERS = 11000; + private static final int OFFSET = 3; + private static final int SCALE = 2; + private static final int ALIGN_OFF = 8; + private static final int UNALIGN_OFF = 5; + + public static void main(String args[]) { + System.out.println("Testing Integer array atomic CAS operations"); + int errn = test(false); + if (errn > 0) { + System.err.println("FAILED: " + errn + " errors"); + System.exit(97); + } + System.out.println("PASSED"); + } + + static int test(boolean test_only) { + AtomicIntegerArray a1 = new AtomicIntegerArray(ARRLEN); + AtomicIntegerArray a2 = new AtomicIntegerArray(ARRLEN); + // Initialize + for (int i=0; i 0 || test_only) + return errn; + + // Initialize + for (int i=0; i= 0; i-=1) { + a.compareAndSet(i, old, -123); + } + } + static void test_vi_neg(AtomicIntegerArray a, int b, int old) { + for (int i = ARRLEN-1; i >= 0; i-=1) { + a.compareAndSet(i, old, b); + } + } + static void test_cp_neg(AtomicIntegerArray a, AtomicIntegerArray b) { + for (int i = ARRLEN-1; i >= 0; i-=1) { + a.compareAndSet(i, -123, b.get(i)); + } + } + static void test_2ci_neg(AtomicIntegerArray a, AtomicIntegerArray b) { + for (int i = ARRLEN-1; i >= 0; i-=1) { + a.compareAndSet(i, 123, -123); + b.compareAndSet(i, 123, -103); + } + } + static void test_2vi_neg(AtomicIntegerArray a, AtomicIntegerArray b, int c, int d) { + for (int i = ARRLEN-1; i >= 0; i-=1) { + a.compareAndSet(i, -123, c); + b.compareAndSet(i, -103, d); + } + } + static void test_ci_oppos(AtomicIntegerArray a, int old) { + int limit = ARRLEN-1; + for (int i = 0; i < ARRLEN; i+=1) { + a.compareAndSet((limit-i), old, -123); + } + } + static void test_vi_oppos(AtomicIntegerArray a, int b, int old) { + int limit = ARRLEN-1; + for (int i = limit; i >= 0; i-=1) { + a.compareAndSet((limit-i), old, b); + } + } + static void test_cp_oppos(AtomicIntegerArray a, AtomicIntegerArray b) { + int limit = ARRLEN-1; + for (int i = 0; i < ARRLEN; i+=1) { + a.compareAndSet(i, -123, b.get(limit-i)); + } + } + static void test_2ci_oppos(AtomicIntegerArray a, AtomicIntegerArray b) { + int limit = ARRLEN-1; + for (int i = 0; i < ARRLEN; i+=1) { + a.compareAndSet((limit-i), 123, -123); + b.compareAndSet(i, 123, -103); + } + } + static void test_2vi_oppos(AtomicIntegerArray a, AtomicIntegerArray b, int c, int d) { + int limit = ARRLEN-1; + for (int i = limit; i >= 0; i-=1) { + a.compareAndSet(i, -123, c); + b.compareAndSet((limit-i), -103, d); + } + } + static void test_ci_off(AtomicIntegerArray a, int old) { + for (int i = 0; i < ARRLEN-OFFSET; i+=1) { + a.compareAndSet((i+OFFSET), old, -123); + } + } + static void test_vi_off(AtomicIntegerArray a, int b, int old) { + for (int i = 0; i < ARRLEN-OFFSET; i+=1) { + a.compareAndSet((i+OFFSET), old, b); + } + } + static void test_cp_off(AtomicIntegerArray a, AtomicIntegerArray b) { + for (int i = 0; i < ARRLEN-OFFSET; i+=1) { + a.compareAndSet((i+OFFSET), -123, b.get(i+OFFSET)); + } + } + static void test_2ci_off(AtomicIntegerArray a, AtomicIntegerArray b) { + for (int i = 0; i < ARRLEN-OFFSET; i+=1) { + a.compareAndSet((i+OFFSET), 123, -123); + b.compareAndSet((i+OFFSET), 123, -103); + } + } + static void test_2vi_off(AtomicIntegerArray a, AtomicIntegerArray b, int c, int d) { + for (int i = 0; i < ARRLEN-OFFSET; i+=1) { + a.compareAndSet((i+OFFSET), -123, c); + b.compareAndSet((i+OFFSET), -103, d); + } + } + static void test_ci_inv(AtomicIntegerArray a, int k, int old) { + for (int i = 0; i < ARRLEN-k; i+=1) { + a.compareAndSet((i+k), old, -123); + } + } + static void test_vi_inv(AtomicIntegerArray a, int b, int k, int old) { + for (int i = 0; i < ARRLEN-k; i+=1) { + a.compareAndSet((i+k), old, b); + } + } + static void test_cp_inv(AtomicIntegerArray a, AtomicIntegerArray b, int k) { + for (int i = 0; i < ARRLEN-k; i+=1) { + a.compareAndSet((i+k), -123, b.get(i+k)); + } + } + static void test_2ci_inv(AtomicIntegerArray a, AtomicIntegerArray b, int k) { + for (int i = 0; i < ARRLEN-k; i+=1) { + a.compareAndSet((i+k), 123, -123); + b.compareAndSet((i+k), 123, -103); + } + } + static void test_2vi_inv(AtomicIntegerArray a, AtomicIntegerArray b, int c, int d, int k) { + for (int i = 0; i < ARRLEN-k; i+=1) { + a.compareAndSet((i+k), -123, c); + b.compareAndSet((i+k), -103, d); + } + } + static void test_ci_scl(AtomicIntegerArray a, int old) { + for (int i = 0; i*SCALE < ARRLEN; i+=1) { + a.compareAndSet((i*SCALE), old, -123); + } + } + static void test_vi_scl(AtomicIntegerArray a, int b, int old) { + for (int i = 0; i*SCALE < ARRLEN; i+=1) { + a.compareAndSet((i*SCALE), old, b); + } + } + static void test_cp_scl(AtomicIntegerArray a, AtomicIntegerArray b) { + for (int i = 0; i*SCALE < ARRLEN; i+=1) { + a.compareAndSet((i*SCALE), -123, b.get(i*SCALE)); + } + } + static void test_2ci_scl(AtomicIntegerArray a, AtomicIntegerArray b) { + for (int i = 0; i*SCALE < ARRLEN; i+=1) { + a.compareAndSet((i*SCALE), 123, -123); + b.compareAndSet((i*SCALE), 123, -103); + } + } + static void test_2vi_scl(AtomicIntegerArray a, AtomicIntegerArray b, int c, int d) { + for (int i = 0; i*SCALE < ARRLEN; i+=1) { + a.compareAndSet((i*SCALE), -123, c); + b.compareAndSet((i*SCALE), -103, d); + } + } + static void test_cp_alndst(AtomicIntegerArray a, AtomicIntegerArray b) { + for (int i = 0; i < ARRLEN-ALIGN_OFF; i+=1) { + a.compareAndSet((i+ALIGN_OFF), -1, b.get(i)); + } + } + static void test_cp_alnsrc(AtomicIntegerArray a, AtomicIntegerArray b) { + for (int i = 0; i < ARRLEN-ALIGN_OFF; i+=1) { + a.getAndSet(i, b.get(i+ALIGN_OFF)); + } + } + static void test_2ci_aln(AtomicIntegerArray a, AtomicIntegerArray b) { + for (int i = 0; i < ARRLEN-ALIGN_OFF; i+=1) { + a.compareAndSet((i+ALIGN_OFF), -1, -123); + b.getAndSet(i, -103); + } + } + static void test_2vi_aln(AtomicIntegerArray a, AtomicIntegerArray b, int c, int d) { + for (int i = 0; i < ARRLEN-ALIGN_OFF; i+=1) { + a.getAndSet(i, c); + b.getAndSet((i+ALIGN_OFF), d); + } + } + static void test_cp_unalndst(AtomicIntegerArray a, AtomicIntegerArray b) { + for (int i = 0; i < ARRLEN-UNALIGN_OFF; i+=1) { + a.compareAndSet((i+UNALIGN_OFF), -1, b.get(i)); + } + } + static void test_cp_unalnsrc(AtomicIntegerArray a, AtomicIntegerArray b) { + for (int i = 0; i < ARRLEN-UNALIGN_OFF; i+=1) { + a.getAndSet(i, b.get(i+UNALIGN_OFF)); + } + } + static void test_2ci_unaln(AtomicIntegerArray a, AtomicIntegerArray b) { + for (int i = 0; i < ARRLEN-UNALIGN_OFF; i+=1) { + a.compareAndSet((i+UNALIGN_OFF), -1, -123); + b.getAndSet(i, -103); + } + } + static void test_2vi_unaln(AtomicIntegerArray a, AtomicIntegerArray b, int c, int d) { + for (int i = 0; i < ARRLEN-UNALIGN_OFF; i+=1) { + a.getAndSet(i, c); + b.getAndSet((i+UNALIGN_OFF), d); + } + } + + static int verify(String text, int i, int elem, int val) { + if (elem != val) { + System.err.println(text + "[" + i + "] = " + elem + " != " + val); + return 1; + } + return 0; + } +} diff -r a413bcd552a4 -r 5fc51c1ecdeb test/compiler/8004867/TestIntAtomicOrdered.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/8004867/TestIntAtomicOrdered.java Tue Mar 05 23:44:54 2013 +0100 @@ -0,0 +1,969 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/** + * @test + * @bug 8004867 + * @summary VM crashing with assert "share/vm/opto/node.hpp:357 - assert(i < _max) failed: oob" + * + * @run main/othervm/timeout=300 -Xbatch -XX:+IgnoreUnrecognizedVMOptions -XX:-TieredCompilation -XX:-OptimizeFill TestIntAtomicOrdered + * @run main/othervm/timeout=300 -Xbatch -XX:+IgnoreUnrecognizedVMOptions -XX:-TieredCompilation -XX:+OptimizeFill TestIntAtomicOrdered + */ + +import java.util.concurrent.atomic.AtomicIntegerArray; + +public class TestIntAtomicOrdered { + private static final int ARRLEN = 97; + private static final int ITERS = 11000; + private static final int OFFSET = 3; + private static final int SCALE = 2; + private static final int ALIGN_OFF = 8; + private static final int UNALIGN_OFF = 5; + + public static void main(String args[]) { + System.out.println("Testing Integer array atomic ordered operations"); + int errn = test(false); + if (errn > 0) { + System.err.println("FAILED: " + errn + " errors"); + System.exit(97); + } + System.out.println("PASSED"); + } + + static int test(boolean test_only) { + AtomicIntegerArray a1 = new AtomicIntegerArray(ARRLEN); + AtomicIntegerArray a2 = new AtomicIntegerArray(ARRLEN); + // Initialize + for (int i=0; i 0 || test_only) + return errn; + + // Initialize + for (int i=0; i= 0; i-=1) { + a.lazySet(i,-123); + } + } + static void test_vi_neg(AtomicIntegerArray a, int b, int old) { + for (int i = ARRLEN-1; i >= 0; i-=1) { + a.lazySet(i, b); + } + } + static void test_cp_neg(AtomicIntegerArray a, AtomicIntegerArray b) { + for (int i = ARRLEN-1; i >= 0; i-=1) { + a.lazySet(i, b.get(i)); + } + } + static void test_2ci_neg(AtomicIntegerArray a, AtomicIntegerArray b) { + for (int i = ARRLEN-1; i >= 0; i-=1) { + a.lazySet(i, -123); + b.lazySet(i, -103); + } + } + static void test_2vi_neg(AtomicIntegerArray a, AtomicIntegerArray b, int c, int d) { + for (int i = ARRLEN-1; i >= 0; i-=1) { + a.lazySet(i, c); + b.lazySet(i, d); + } + } + static void test_ci_oppos(AtomicIntegerArray a, int old) { + int limit = ARRLEN-1; + for (int i = 0; i < ARRLEN; i+=1) { + a.lazySet((limit-i), -123); + } + } + static void test_vi_oppos(AtomicIntegerArray a, int b, int old) { + int limit = ARRLEN-1; + for (int i = limit; i >= 0; i-=1) { + a.lazySet((limit-i), b); + } + } + static void test_cp_oppos(AtomicIntegerArray a, AtomicIntegerArray b) { + int limit = ARRLEN-1; + for (int i = 0; i < ARRLEN; i+=1) { + a.lazySet(i, b.get(limit-i)); + } + } + static void test_2ci_oppos(AtomicIntegerArray a, AtomicIntegerArray b) { + int limit = ARRLEN-1; + for (int i = 0; i < ARRLEN; i+=1) { + a.lazySet((limit-i), -123); + b.lazySet(i, -103); + } + } + static void test_2vi_oppos(AtomicIntegerArray a, AtomicIntegerArray b, int c, int d) { + int limit = ARRLEN-1; + for (int i = limit; i >= 0; i-=1) { + a.lazySet(i, c); + b.lazySet((limit-i), d); + } + } + static void test_ci_off(AtomicIntegerArray a, int old) { + for (int i = 0; i < ARRLEN-OFFSET; i+=1) { + a.lazySet((i+OFFSET), -123); + } + } + static void test_vi_off(AtomicIntegerArray a, int b, int old) { + for (int i = 0; i < ARRLEN-OFFSET; i+=1) { + a.lazySet((i+OFFSET), b); + } + } + static void test_cp_off(AtomicIntegerArray a, AtomicIntegerArray b) { + for (int i = 0; i < ARRLEN-OFFSET; i+=1) { + a.lazySet((i+OFFSET), b.get(i+OFFSET)); + } + } + static void test_2ci_off(AtomicIntegerArray a, AtomicIntegerArray b) { + for (int i = 0; i < ARRLEN-OFFSET; i+=1) { + a.lazySet((i+OFFSET), -123); + b.lazySet((i+OFFSET), -103); + } + } + static void test_2vi_off(AtomicIntegerArray a, AtomicIntegerArray b, int c, int d) { + for (int i = 0; i < ARRLEN-OFFSET; i+=1) { + a.lazySet((i+OFFSET), c); + b.lazySet((i+OFFSET), d); + } + } + static void test_ci_inv(AtomicIntegerArray a, int k, int old) { + for (int i = 0; i < ARRLEN-k; i+=1) { + a.lazySet((i+k),-123); + } + } + static void test_vi_inv(AtomicIntegerArray a, int b, int k, int old) { + for (int i = 0; i < ARRLEN-k; i+=1) { + a.lazySet((i+k), b); + } + } + static void test_cp_inv(AtomicIntegerArray a, AtomicIntegerArray b, int k) { + for (int i = 0; i < ARRLEN-k; i+=1) { + a.lazySet((i+k), b.get(i+k)); + } + } + static void test_2ci_inv(AtomicIntegerArray a, AtomicIntegerArray b, int k) { + for (int i = 0; i < ARRLEN-k; i+=1) { + a.lazySet((i+k), -123); + b.lazySet((i+k), -103); + } + } + static void test_2vi_inv(AtomicIntegerArray a, AtomicIntegerArray b, int c, int d, int k) { + for (int i = 0; i < ARRLEN-k; i+=1) { + a.lazySet((i+k), c); + b.lazySet((i+k), d); + } + } + static void test_ci_scl(AtomicIntegerArray a, int old) { + for (int i = 0; i*SCALE < ARRLEN; i+=1) { + a.lazySet((i*SCALE), -123); + } + } + static void test_vi_scl(AtomicIntegerArray a, int b, int old) { + for (int i = 0; i*SCALE < ARRLEN; i+=1) { + a.lazySet((i*SCALE), b); + } + } + static void test_cp_scl(AtomicIntegerArray a, AtomicIntegerArray b) { + for (int i = 0; i*SCALE < ARRLEN; i+=1) { + a.lazySet((i*SCALE), b.get(i*SCALE)); + } + } + static void test_2ci_scl(AtomicIntegerArray a, AtomicIntegerArray b) { + for (int i = 0; i*SCALE < ARRLEN; i+=1) { + a.lazySet((i*SCALE), -123); + b.lazySet((i*SCALE), -103); + } + } + static void test_2vi_scl(AtomicIntegerArray a, AtomicIntegerArray b, int c, int d) { + for (int i = 0; i*SCALE < ARRLEN; i+=1) { + a.lazySet((i*SCALE), c); + b.lazySet((i*SCALE), d); + } + } + static void test_cp_alndst(AtomicIntegerArray a, AtomicIntegerArray b) { + for (int i = 0; i < ARRLEN-ALIGN_OFF; i+=1) { + a.lazySet((i+ALIGN_OFF), b.get(i)); + } + } + static void test_cp_alnsrc(AtomicIntegerArray a, AtomicIntegerArray b) { + for (int i = 0; i < ARRLEN-ALIGN_OFF; i+=1) { + a.lazySet(i, b.get(i+ALIGN_OFF)); + } + } + static void test_2ci_aln(AtomicIntegerArray a, AtomicIntegerArray b) { + for (int i = 0; i < ARRLEN-ALIGN_OFF; i+=1) { + a.lazySet((i+ALIGN_OFF), -123); + b.lazySet(i, -103); + } + } + static void test_2vi_aln(AtomicIntegerArray a, AtomicIntegerArray b, int c, int d) { + for (int i = 0; i < ARRLEN-ALIGN_OFF; i+=1) { + a.lazySet(i, c); + b.lazySet((i+ALIGN_OFF), d); + } + } + static void test_cp_unalndst(AtomicIntegerArray a, AtomicIntegerArray b) { + for (int i = 0; i < ARRLEN-UNALIGN_OFF; i+=1) { + a.lazySet((i+UNALIGN_OFF), b.get(i)); + } + } + static void test_cp_unalnsrc(AtomicIntegerArray a, AtomicIntegerArray b) { + for (int i = 0; i < ARRLEN-UNALIGN_OFF; i+=1) { + a.lazySet(i, b.get(i+UNALIGN_OFF)); + } + } + static void test_2ci_unaln(AtomicIntegerArray a, AtomicIntegerArray b) { + for (int i = 0; i < ARRLEN-UNALIGN_OFF; i+=1) { + a.lazySet((i+UNALIGN_OFF), -123); + b.lazySet(i, -103); + } + } + static void test_2vi_unaln(AtomicIntegerArray a, AtomicIntegerArray b, int c, int d) { + for (int i = 0; i < ARRLEN-UNALIGN_OFF; i+=1) { + a.lazySet(i, c); + b.lazySet((i+UNALIGN_OFF), d); + } + } + + static int verify(String text, int i, int elem, int val) { + if (elem != val) { + System.err.println(text + "[" + i + "] = " + elem + " != " + val); + return 1; + } + return 0; + } +} diff -r a413bcd552a4 -r 5fc51c1ecdeb test/compiler/8004867/TestIntAtomicVolatile.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/8004867/TestIntAtomicVolatile.java Tue Mar 05 23:44:54 2013 +0100 @@ -0,0 +1,969 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/** + * @test + * @bug 8004867 + * @summary VM crashing with assert "share/vm/opto/node.hpp:357 - assert(i < _max) failed: oob" + * + * @run main/othervm/timeout=300 -Xbatch -XX:+IgnoreUnrecognizedVMOptions -XX:-TieredCompilation -XX:-OptimizeFill TestIntAtomicVolatile + * @run main/othervm/timeout=300 -Xbatch -XX:+IgnoreUnrecognizedVMOptions -XX:-TieredCompilation -XX:+OptimizeFill TestIntAtomicVolatile + */ + +import java.util.concurrent.atomic.AtomicIntegerArray; + +public class TestIntAtomicVolatile { + private static final int ARRLEN = 97; + private static final int ITERS = 11000; + private static final int OFFSET = 3; + private static final int SCALE = 2; + private static final int ALIGN_OFF = 8; + private static final int UNALIGN_OFF = 5; + + public static void main(String args[]) { + System.out.println("Testing Integer array atomic volatile operations"); + int errn = test(false); + if (errn > 0) { + System.err.println("FAILED: " + errn + " errors"); + System.exit(97); + } + System.out.println("PASSED"); + } + + static int test(boolean test_only) { + AtomicIntegerArray a1 = new AtomicIntegerArray(ARRLEN); + AtomicIntegerArray a2 = new AtomicIntegerArray(ARRLEN); + // Initialize + for (int i=0; i 0 || test_only) + return errn; + + // Initialize + for (int i=0; i= 0; i-=1) { + a.set(i,-123); + } + } + static void test_vi_neg(AtomicIntegerArray a, int b, int old) { + for (int i = ARRLEN-1; i >= 0; i-=1) { + a.set(i, b); + } + } + static void test_cp_neg(AtomicIntegerArray a, AtomicIntegerArray b) { + for (int i = ARRLEN-1; i >= 0; i-=1) { + a.set(i, b.get(i)); + } + } + static void test_2ci_neg(AtomicIntegerArray a, AtomicIntegerArray b) { + for (int i = ARRLEN-1; i >= 0; i-=1) { + a.set(i, -123); + b.set(i, -103); + } + } + static void test_2vi_neg(AtomicIntegerArray a, AtomicIntegerArray b, int c, int d) { + for (int i = ARRLEN-1; i >= 0; i-=1) { + a.set(i, c); + b.set(i, d); + } + } + static void test_ci_oppos(AtomicIntegerArray a, int old) { + int limit = ARRLEN-1; + for (int i = 0; i < ARRLEN; i+=1) { + a.set((limit-i), -123); + } + } + static void test_vi_oppos(AtomicIntegerArray a, int b, int old) { + int limit = ARRLEN-1; + for (int i = limit; i >= 0; i-=1) { + a.set((limit-i), b); + } + } + static void test_cp_oppos(AtomicIntegerArray a, AtomicIntegerArray b) { + int limit = ARRLEN-1; + for (int i = 0; i < ARRLEN; i+=1) { + a.set(i, b.get(limit-i)); + } + } + static void test_2ci_oppos(AtomicIntegerArray a, AtomicIntegerArray b) { + int limit = ARRLEN-1; + for (int i = 0; i < ARRLEN; i+=1) { + a.set((limit-i), -123); + b.set(i, -103); + } + } + static void test_2vi_oppos(AtomicIntegerArray a, AtomicIntegerArray b, int c, int d) { + int limit = ARRLEN-1; + for (int i = limit; i >= 0; i-=1) { + a.set(i, c); + b.set((limit-i), d); + } + } + static void test_ci_off(AtomicIntegerArray a, int old) { + for (int i = 0; i < ARRLEN-OFFSET; i+=1) { + a.set((i+OFFSET), -123); + } + } + static void test_vi_off(AtomicIntegerArray a, int b, int old) { + for (int i = 0; i < ARRLEN-OFFSET; i+=1) { + a.set((i+OFFSET), b); + } + } + static void test_cp_off(AtomicIntegerArray a, AtomicIntegerArray b) { + for (int i = 0; i < ARRLEN-OFFSET; i+=1) { + a.set((i+OFFSET), b.get(i+OFFSET)); + } + } + static void test_2ci_off(AtomicIntegerArray a, AtomicIntegerArray b) { + for (int i = 0; i < ARRLEN-OFFSET; i+=1) { + a.set((i+OFFSET), -123); + b.set((i+OFFSET), -103); + } + } + static void test_2vi_off(AtomicIntegerArray a, AtomicIntegerArray b, int c, int d) { + for (int i = 0; i < ARRLEN-OFFSET; i+=1) { + a.set((i+OFFSET), c); + b.set((i+OFFSET), d); + } + } + static void test_ci_inv(AtomicIntegerArray a, int k, int old) { + for (int i = 0; i < ARRLEN-k; i+=1) { + a.set((i+k),-123); + } + } + static void test_vi_inv(AtomicIntegerArray a, int b, int k, int old) { + for (int i = 0; i < ARRLEN-k; i+=1) { + a.set((i+k), b); + } + } + static void test_cp_inv(AtomicIntegerArray a, AtomicIntegerArray b, int k) { + for (int i = 0; i < ARRLEN-k; i+=1) { + a.set((i+k), b.get(i+k)); + } + } + static void test_2ci_inv(AtomicIntegerArray a, AtomicIntegerArray b, int k) { + for (int i = 0; i < ARRLEN-k; i+=1) { + a.set((i+k), -123); + b.set((i+k), -103); + } + } + static void test_2vi_inv(AtomicIntegerArray a, AtomicIntegerArray b, int c, int d, int k) { + for (int i = 0; i < ARRLEN-k; i+=1) { + a.set((i+k), c); + b.set((i+k), d); + } + } + static void test_ci_scl(AtomicIntegerArray a, int old) { + for (int i = 0; i*SCALE < ARRLEN; i+=1) { + a.set((i*SCALE), -123); + } + } + static void test_vi_scl(AtomicIntegerArray a, int b, int old) { + for (int i = 0; i*SCALE < ARRLEN; i+=1) { + a.set((i*SCALE), b); + } + } + static void test_cp_scl(AtomicIntegerArray a, AtomicIntegerArray b) { + for (int i = 0; i*SCALE < ARRLEN; i+=1) { + a.set((i*SCALE), b.get(i*SCALE)); + } + } + static void test_2ci_scl(AtomicIntegerArray a, AtomicIntegerArray b) { + for (int i = 0; i*SCALE < ARRLEN; i+=1) { + a.set((i*SCALE), -123); + b.set((i*SCALE), -103); + } + } + static void test_2vi_scl(AtomicIntegerArray a, AtomicIntegerArray b, int c, int d) { + for (int i = 0; i*SCALE < ARRLEN; i+=1) { + a.set((i*SCALE), c); + b.set((i*SCALE), d); + } + } + static void test_cp_alndst(AtomicIntegerArray a, AtomicIntegerArray b) { + for (int i = 0; i < ARRLEN-ALIGN_OFF; i+=1) { + a.set((i+ALIGN_OFF), b.get(i)); + } + } + static void test_cp_alnsrc(AtomicIntegerArray a, AtomicIntegerArray b) { + for (int i = 0; i < ARRLEN-ALIGN_OFF; i+=1) { + a.set(i, b.get(i+ALIGN_OFF)); + } + } + static void test_2ci_aln(AtomicIntegerArray a, AtomicIntegerArray b) { + for (int i = 0; i < ARRLEN-ALIGN_OFF; i+=1) { + a.set((i+ALIGN_OFF), -123); + b.set(i, -103); + } + } + static void test_2vi_aln(AtomicIntegerArray a, AtomicIntegerArray b, int c, int d) { + for (int i = 0; i < ARRLEN-ALIGN_OFF; i+=1) { + a.set(i, c); + b.set((i+ALIGN_OFF), d); + } + } + static void test_cp_unalndst(AtomicIntegerArray a, AtomicIntegerArray b) { + for (int i = 0; i < ARRLEN-UNALIGN_OFF; i+=1) { + a.set((i+UNALIGN_OFF), b.get(i)); + } + } + static void test_cp_unalnsrc(AtomicIntegerArray a, AtomicIntegerArray b) { + for (int i = 0; i < ARRLEN-UNALIGN_OFF; i+=1) { + a.set(i, b.get(i+UNALIGN_OFF)); + } + } + static void test_2ci_unaln(AtomicIntegerArray a, AtomicIntegerArray b) { + for (int i = 0; i < ARRLEN-UNALIGN_OFF; i+=1) { + a.set((i+UNALIGN_OFF), -123); + b.set(i, -103); + } + } + static void test_2vi_unaln(AtomicIntegerArray a, AtomicIntegerArray b, int c, int d) { + for (int i = 0; i < ARRLEN-UNALIGN_OFF; i+=1) { + a.set(i, c); + b.set((i+UNALIGN_OFF), d); + } + } + + static int verify(String text, int i, int elem, int val) { + if (elem != val) { + System.err.println(text + "[" + i + "] = " + elem + " != " + val); + return 1; + } + return 0; + } +} diff -r a413bcd552a4 -r 5fc51c1ecdeb test/compiler/8004867/TestIntUnsafeCAS.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/8004867/TestIntUnsafeCAS.java Tue Mar 05 23:44:54 2013 +0100 @@ -0,0 +1,998 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/** + * @test + * @bug 8004867 + * @summary VM crashing with assert "share/vm/opto/node.hpp:357 - assert(i < _max) failed: oob" + * + * @run main/othervm/timeout=300 -Xbatch -XX:+IgnoreUnrecognizedVMOptions -XX:-TieredCompilation -XX:-OptimizeFill TestIntUnsafeCAS + * @run main/othervm/timeout=300 -Xbatch -XX:+IgnoreUnrecognizedVMOptions -XX:-TieredCompilation -XX:+OptimizeFill TestIntUnsafeCAS + */ + +import sun.misc.Unsafe; +import java.lang.reflect.*; + +public class TestIntUnsafeCAS { + private static final int ARRLEN = 97; + private static final int ITERS = 11000; + private static final int OFFSET = 3; + private static final int SCALE = 2; + private static final int ALIGN_OFF = 8; + private static final int UNALIGN_OFF = 5; + + private static final Unsafe unsafe; + private static final int BASE; + static { + try { + Class c = TestIntUnsafeCAS.class.getClassLoader().loadClass("sun.misc.Unsafe"); + Field f = c.getDeclaredField("theUnsafe"); + f.setAccessible(true); + unsafe = (Unsafe)f.get(c); + BASE = unsafe.arrayBaseOffset(int[].class); + } catch (Exception e) { + InternalError err = new InternalError(); + err.initCause(e); + throw err; + } + } + + public static void main(String args[]) { + System.out.println("Testing Integer array unsafe CAS operations"); + int errn = test(false); + if (errn > 0) { + System.err.println("FAILED: " + errn + " errors"); + System.exit(97); + } + System.out.println("PASSED"); + } + + static int test(boolean test_only) { + int[] a1 = new int[ARRLEN]; + int[] a2 = new int[ARRLEN]; + // Initialize + for (int i=0; i 0 || test_only) + return errn; + + // Initialize + for (int i=0; i= 0; i-=1) { + unsafe.compareAndSwapInt(a, byte_offset(i), old, -123); + } + } + static void test_vi_neg(int[] a, int b, int old) { + for (int i = ARRLEN-1; i >= 0; i-=1) { + unsafe.compareAndSwapInt(a, byte_offset(i), old, b); + } + } + static void test_cp_neg(int[] a, int[] b) { + for (int i = ARRLEN-1; i >= 0; i-=1) { + unsafe.compareAndSwapInt(a, byte_offset(i), -123, b[i]); + } + } + static void test_2ci_neg(int[] a, int[] b) { + for (int i = ARRLEN-1; i >= 0; i-=1) { + unsafe.compareAndSwapInt(a, byte_offset(i), 123, -123); + unsafe.compareAndSwapInt(b, byte_offset(i), 123, -103); + } + } + static void test_2vi_neg(int[] a, int[] b, int c, int d) { + for (int i = ARRLEN-1; i >= 0; i-=1) { + unsafe.compareAndSwapInt(a, byte_offset(i), -123, c); + unsafe.compareAndSwapInt(b, byte_offset(i), -103, d); + } + } + static void test_ci_oppos(int[] a, int old) { + int limit = ARRLEN-1; + for (int i = 0; i < ARRLEN; i+=1) { + unsafe.compareAndSwapInt(a, byte_offset(limit-i), old, -123); + } + } + static void test_vi_oppos(int[] a, int b, int old) { + int limit = ARRLEN-1; + for (int i = limit; i >= 0; i-=1) { + unsafe.compareAndSwapInt(a, byte_offset(limit-i), old, b); + } + } + static void test_cp_oppos(int[] a, int[] b) { + int limit = ARRLEN-1; + for (int i = 0; i < ARRLEN; i+=1) { + unsafe.compareAndSwapInt(a, byte_offset(i), -123, b[limit-i]); + } + } + static void test_2ci_oppos(int[] a, int[] b) { + int limit = ARRLEN-1; + for (int i = 0; i < ARRLEN; i+=1) { + unsafe.compareAndSwapInt(a, byte_offset(limit-i), 123, -123); + unsafe.compareAndSwapInt(b, byte_offset(i), 123, -103); + } + } + static void test_2vi_oppos(int[] a, int[] b, int c, int d) { + int limit = ARRLEN-1; + for (int i = limit; i >= 0; i-=1) { + unsafe.compareAndSwapInt(a, byte_offset(i), -123, c); + unsafe.compareAndSwapInt(b, byte_offset(limit-i), -103, d); + } + } + static void test_ci_off(int[] a, int old) { + for (int i = 0; i < ARRLEN-OFFSET; i+=1) { + unsafe.compareAndSwapInt(a, byte_offset(i+OFFSET), old, -123); + } + } + static void test_vi_off(int[] a, int b, int old) { + for (int i = 0; i < ARRLEN-OFFSET; i+=1) { + unsafe.compareAndSwapInt(a, byte_offset(i+OFFSET), old, b); + } + } + static void test_cp_off(int[] a, int[] b) { + for (int i = 0; i < ARRLEN-OFFSET; i+=1) { + unsafe.compareAndSwapInt(a, byte_offset(i+OFFSET), -123, b[i+OFFSET]); + } + } + static void test_2ci_off(int[] a, int[] b) { + for (int i = 0; i < ARRLEN-OFFSET; i+=1) { + unsafe.compareAndSwapInt(a, byte_offset(i+OFFSET), 123, -123); + unsafe.compareAndSwapInt(b, byte_offset(i+OFFSET), 123, -103); + } + } + static void test_2vi_off(int[] a, int[] b, int c, int d) { + for (int i = 0; i < ARRLEN-OFFSET; i+=1) { + unsafe.compareAndSwapInt(a, byte_offset(i+OFFSET), -123, c); + unsafe.compareAndSwapInt(b, byte_offset(i+OFFSET), -103, d); + } + } + static void test_ci_inv(int[] a, int k, int old) { + for (int i = 0; i < ARRLEN-k; i+=1) { + unsafe.compareAndSwapInt(a, byte_offset(i+k), old, -123); + } + } + static void test_vi_inv(int[] a, int b, int k, int old) { + for (int i = 0; i < ARRLEN-k; i+=1) { + unsafe.compareAndSwapInt(a, byte_offset(i+k), old, b); + } + } + static void test_cp_inv(int[] a, int[] b, int k) { + for (int i = 0; i < ARRLEN-k; i+=1) { + unsafe.compareAndSwapInt(a, byte_offset(i+k), -123, b[i+k]); + } + } + static void test_2ci_inv(int[] a, int[] b, int k) { + for (int i = 0; i < ARRLEN-k; i+=1) { + unsafe.compareAndSwapInt(a, byte_offset(i+k), 123, -123); + unsafe.compareAndSwapInt(b, byte_offset(i+k), 123, -103); + } + } + static void test_2vi_inv(int[] a, int[] b, int c, int d, int k) { + for (int i = 0; i < ARRLEN-k; i+=1) { + unsafe.compareAndSwapInt(a, byte_offset(i+k), -123, c); + unsafe.compareAndSwapInt(b, byte_offset(i+k), -103, d); + } + } + static void test_ci_scl(int[] a, int old) { + for (int i = 0; i*SCALE < ARRLEN; i+=1) { + unsafe.compareAndSwapInt(a, byte_offset(i*SCALE), old, -123); + } + } + static void test_vi_scl(int[] a, int b, int old) { + for (int i = 0; i*SCALE < ARRLEN; i+=1) { + unsafe.compareAndSwapInt(a, byte_offset(i*SCALE), old, b); + } + } + static void test_cp_scl(int[] a, int[] b) { + for (int i = 0; i*SCALE < ARRLEN; i+=1) { + unsafe.compareAndSwapInt(a, byte_offset(i*SCALE), -123, b[i*SCALE]); + } + } + static void test_2ci_scl(int[] a, int[] b) { + for (int i = 0; i*SCALE < ARRLEN; i+=1) { + unsafe.compareAndSwapInt(a, byte_offset(i*SCALE), 123, -123); + unsafe.compareAndSwapInt(b, byte_offset(i*SCALE), 123, -103); + } + } + static void test_2vi_scl(int[] a, int[] b, int c, int d) { + for (int i = 0; i*SCALE < ARRLEN; i+=1) { + unsafe.compareAndSwapInt(a, byte_offset(i*SCALE), -123, c); + unsafe.compareAndSwapInt(b, byte_offset(i*SCALE), -103, d); + } + } + static void test_cp_alndst(int[] a, int[] b) { + for (int i = 0; i < ARRLEN-ALIGN_OFF; i+=1) { + unsafe.compareAndSwapInt(a, byte_offset(i+ALIGN_OFF), -1, b[i]); + } + } + static void test_cp_alnsrc(int[] a, int[] b) { + for (int i = 0; i < ARRLEN-ALIGN_OFF; i+=1) { + int old = unsafe.getIntVolatile(a, byte_offset(i)); + unsafe.compareAndSwapInt(a, byte_offset(i), old, b[i+ALIGN_OFF]); + } + } + static void test_2ci_aln(int[] a, int[] b) { + for (int i = 0; i < ARRLEN-ALIGN_OFF; i+=1) { + unsafe.compareAndSwapInt(a, byte_offset(i+ALIGN_OFF), -1, -123); + int old = unsafe.getIntVolatile(b, byte_offset(i)); + unsafe.compareAndSwapInt(b, byte_offset(i), old, -103); + } + } + static void test_2vi_aln(int[] a, int[] b, int c, int d) { + for (int i = 0; i < ARRLEN-ALIGN_OFF; i+=1) { + int old = unsafe.getIntVolatile(a, byte_offset(i)); + unsafe.compareAndSwapInt(a, byte_offset(i), old, c); + old = unsafe.getIntVolatile(b, byte_offset(i+ALIGN_OFF)); + unsafe.compareAndSwapInt(b, byte_offset(i+ALIGN_OFF), old, d); + } + } + static void test_cp_unalndst(int[] a, int[] b) { + for (int i = 0; i < ARRLEN-UNALIGN_OFF; i+=1) { + unsafe.compareAndSwapInt(a, byte_offset(i+UNALIGN_OFF), -1, b[i]); + } + } + static void test_cp_unalnsrc(int[] a, int[] b) { + for (int i = 0; i < ARRLEN-UNALIGN_OFF; i+=1) { + int old = unsafe.getIntVolatile(a, byte_offset(i)); + unsafe.compareAndSwapInt(a, byte_offset(i), old, b[i+UNALIGN_OFF]); + } + } + static void test_2ci_unaln(int[] a, int[] b) { + for (int i = 0; i < ARRLEN-UNALIGN_OFF; i+=1) { + unsafe.compareAndSwapInt(a, byte_offset(i+UNALIGN_OFF), -1, -123); + int old = unsafe.getIntVolatile(b, byte_offset(i)); + unsafe.compareAndSwapInt(b, byte_offset(i), old, -103); + } + } + static void test_2vi_unaln(int[] a, int[] b, int c, int d) { + for (int i = 0; i < ARRLEN-UNALIGN_OFF; i+=1) { + int old = unsafe.getIntVolatile(a, byte_offset(i)); + unsafe.compareAndSwapInt(a, byte_offset(i), old, c); + old = unsafe.getIntVolatile(b, byte_offset(i+UNALIGN_OFF)); + unsafe.compareAndSwapInt(b, byte_offset(i+UNALIGN_OFF), old, d); + } + } + + static int verify(String text, int i, int elem, int val) { + if (elem != val) { + System.err.println(text + "[" + i + "] = " + elem + " != " + val); + return 1; + } + return 0; + } +} diff -r a413bcd552a4 -r 5fc51c1ecdeb test/compiler/8004867/TestIntUnsafeOrdered.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/8004867/TestIntUnsafeOrdered.java Tue Mar 05 23:44:54 2013 +0100 @@ -0,0 +1,990 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/** + * @test + * @bug 8004867 + * @summary VM crashing with assert "share/vm/opto/node.hpp:357 - assert(i < _max) failed: oob" + * + * @run main/othervm/timeout=300 -Xbatch -XX:+IgnoreUnrecognizedVMOptions -XX:-TieredCompilation -XX:-OptimizeFill TestIntUnsafeOrdered + * @run main/othervm/timeout=300 -Xbatch -XX:+IgnoreUnrecognizedVMOptions -XX:-TieredCompilation -XX:+OptimizeFill TestIntUnsafeOrdered + */ + +import sun.misc.Unsafe; +import java.lang.reflect.*; + +public class TestIntUnsafeOrdered { + private static final int ARRLEN = 97; + private static final int ITERS = 11000; + private static final int OFFSET = 3; + private static final int SCALE = 2; + private static final int ALIGN_OFF = 8; + private static final int UNALIGN_OFF = 5; + + private static final Unsafe unsafe; + private static final int BASE; + static { + try { + Class c = TestIntUnsafeOrdered.class.getClassLoader().loadClass("sun.misc.Unsafe"); + Field f = c.getDeclaredField("theUnsafe"); + f.setAccessible(true); + unsafe = (Unsafe)f.get(c); + BASE = unsafe.arrayBaseOffset(int[].class); + } catch (Exception e) { + InternalError err = new InternalError(); + err.initCause(e); + throw err; + } + } + + public static void main(String args[]) { + System.out.println("Testing Integer array unsafe ordered operations"); + int errn = test(false); + if (errn > 0) { + System.err.println("FAILED: " + errn + " errors"); + System.exit(97); + } + System.out.println("PASSED"); + } + + static int test(boolean test_only) { + int[] a1 = new int[ARRLEN]; + int[] a2 = new int[ARRLEN]; + // Initialize + for (int i=0; i 0 || test_only) + return errn; + + // Initialize + for (int i=0; i= 0; i-=1) { + unsafe.putOrderedInt(a, byte_offset(i), -123); + } + } + static void test_vi_neg(int[] a, int b, int old) { + for (int i = ARRLEN-1; i >= 0; i-=1) { + unsafe.putOrderedInt(a, byte_offset(i), b); + } + } + static void test_cp_neg(int[] a, int[] b) { + for (int i = ARRLEN-1; i >= 0; i-=1) { + unsafe.putOrderedInt(a, byte_offset(i), b[i]); + } + } + static void test_2ci_neg(int[] a, int[] b) { + for (int i = ARRLEN-1; i >= 0; i-=1) { + unsafe.putOrderedInt(a, byte_offset(i), -123); + unsafe.putOrderedInt(b, byte_offset(i), -103); + } + } + static void test_2vi_neg(int[] a, int[] b, int c, int d) { + for (int i = ARRLEN-1; i >= 0; i-=1) { + unsafe.putOrderedInt(a, byte_offset(i), c); + unsafe.putOrderedInt(b, byte_offset(i), d); + } + } + static void test_ci_oppos(int[] a, int old) { + int limit = ARRLEN-1; + for (int i = 0; i < ARRLEN; i+=1) { + unsafe.putOrderedInt(a, byte_offset(limit-i), -123); + } + } + static void test_vi_oppos(int[] a, int b, int old) { + int limit = ARRLEN-1; + for (int i = limit; i >= 0; i-=1) { + unsafe.putOrderedInt(a, byte_offset(limit-i), b); + } + } + static void test_cp_oppos(int[] a, int[] b) { + int limit = ARRLEN-1; + for (int i = 0; i < ARRLEN; i+=1) { + unsafe.putOrderedInt(a, byte_offset(i), b[limit-i]); + } + } + static void test_2ci_oppos(int[] a, int[] b) { + int limit = ARRLEN-1; + for (int i = 0; i < ARRLEN; i+=1) { + unsafe.putOrderedInt(a, byte_offset(limit-i), -123); + unsafe.putOrderedInt(b, byte_offset(i), -103); + } + } + static void test_2vi_oppos(int[] a, int[] b, int c, int d) { + int limit = ARRLEN-1; + for (int i = limit; i >= 0; i-=1) { + unsafe.putOrderedInt(a, byte_offset(i), c); + unsafe.putOrderedInt(b, byte_offset(limit-i), d); + } + } + static void test_ci_off(int[] a, int old) { + for (int i = 0; i < ARRLEN-OFFSET; i+=1) { + unsafe.putOrderedInt(a, byte_offset(i+OFFSET), -123); + } + } + static void test_vi_off(int[] a, int b, int old) { + for (int i = 0; i < ARRLEN-OFFSET; i+=1) { + unsafe.putOrderedInt(a, byte_offset(i+OFFSET), b); + } + } + static void test_cp_off(int[] a, int[] b) { + for (int i = 0; i < ARRLEN-OFFSET; i+=1) { + unsafe.putOrderedInt(a, byte_offset(i+OFFSET), b[i+OFFSET]); + } + } + static void test_2ci_off(int[] a, int[] b) { + for (int i = 0; i < ARRLEN-OFFSET; i+=1) { + unsafe.putOrderedInt(a, byte_offset(i+OFFSET), -123); + unsafe.putOrderedInt(b, byte_offset(i+OFFSET), -103); + } + } + static void test_2vi_off(int[] a, int[] b, int c, int d) { + for (int i = 0; i < ARRLEN-OFFSET; i+=1) { + unsafe.putOrderedInt(a, byte_offset(i+OFFSET), c); + unsafe.putOrderedInt(b, byte_offset(i+OFFSET), d); + } + } + static void test_ci_inv(int[] a, int k, int old) { + for (int i = 0; i < ARRLEN-k; i+=1) { + unsafe.putOrderedInt(a, byte_offset(i+k), -123); + } + } + static void test_vi_inv(int[] a, int b, int k, int old) { + for (int i = 0; i < ARRLEN-k; i+=1) { + unsafe.putOrderedInt(a, byte_offset(i+k), b); + } + } + static void test_cp_inv(int[] a, int[] b, int k) { + for (int i = 0; i < ARRLEN-k; i+=1) { + unsafe.putOrderedInt(a, byte_offset(i+k), b[i+k]); + } + } + static void test_2ci_inv(int[] a, int[] b, int k) { + for (int i = 0; i < ARRLEN-k; i+=1) { + unsafe.putOrderedInt(a, byte_offset(i+k), -123); + unsafe.putOrderedInt(b, byte_offset(i+k), -103); + } + } + static void test_2vi_inv(int[] a, int[] b, int c, int d, int k) { + for (int i = 0; i < ARRLEN-k; i+=1) { + unsafe.putOrderedInt(a, byte_offset(i+k), c); + unsafe.putOrderedInt(b, byte_offset(i+k), d); + } + } + static void test_ci_scl(int[] a, int old) { + for (int i = 0; i*SCALE < ARRLEN; i+=1) { + unsafe.putOrderedInt(a, byte_offset(i*SCALE), -123); + } + } + static void test_vi_scl(int[] a, int b, int old) { + for (int i = 0; i*SCALE < ARRLEN; i+=1) { + unsafe.putOrderedInt(a, byte_offset(i*SCALE), b); + } + } + static void test_cp_scl(int[] a, int[] b) { + for (int i = 0; i*SCALE < ARRLEN; i+=1) { + unsafe.putOrderedInt(a, byte_offset(i*SCALE), b[i*SCALE]); + } + } + static void test_2ci_scl(int[] a, int[] b) { + for (int i = 0; i*SCALE < ARRLEN; i+=1) { + unsafe.putOrderedInt(a, byte_offset(i*SCALE), -123); + unsafe.putOrderedInt(b, byte_offset(i*SCALE), -103); + } + } + static void test_2vi_scl(int[] a, int[] b, int c, int d) { + for (int i = 0; i*SCALE < ARRLEN; i+=1) { + unsafe.putOrderedInt(a, byte_offset(i*SCALE), c); + unsafe.putOrderedInt(b, byte_offset(i*SCALE), d); + } + } + static void test_cp_alndst(int[] a, int[] b) { + for (int i = 0; i < ARRLEN-ALIGN_OFF; i+=1) { + unsafe.putOrderedInt(a, byte_offset(i+ALIGN_OFF), b[i]); + } + } + static void test_cp_alnsrc(int[] a, int[] b) { + for (int i = 0; i < ARRLEN-ALIGN_OFF; i+=1) { + unsafe.putOrderedInt(a, byte_offset(i), b[i+ALIGN_OFF]); + } + } + static void test_2ci_aln(int[] a, int[] b) { + for (int i = 0; i < ARRLEN-ALIGN_OFF; i+=1) { + unsafe.putOrderedInt(a, byte_offset(i+ALIGN_OFF), -123); + unsafe.putOrderedInt(b, byte_offset(i), -103); + } + } + static void test_2vi_aln(int[] a, int[] b, int c, int d) { + for (int i = 0; i < ARRLEN-ALIGN_OFF; i+=1) { + unsafe.putOrderedInt(a, byte_offset(i), c); + unsafe.putOrderedInt(b, byte_offset(i+ALIGN_OFF), d); + } + } + static void test_cp_unalndst(int[] a, int[] b) { + for (int i = 0; i < ARRLEN-UNALIGN_OFF; i+=1) { + unsafe.putOrderedInt(a, byte_offset(i+UNALIGN_OFF), b[i]); + } + } + static void test_cp_unalnsrc(int[] a, int[] b) { + for (int i = 0; i < ARRLEN-UNALIGN_OFF; i+=1) { + unsafe.putOrderedInt(a, byte_offset(i), b[i+UNALIGN_OFF]); + } + } + static void test_2ci_unaln(int[] a, int[] b) { + for (int i = 0; i < ARRLEN-UNALIGN_OFF; i+=1) { + unsafe.putOrderedInt(a, byte_offset(i+UNALIGN_OFF), -123); + unsafe.putOrderedInt(b, byte_offset(i), -103); + } + } + static void test_2vi_unaln(int[] a, int[] b, int c, int d) { + for (int i = 0; i < ARRLEN-UNALIGN_OFF; i+=1) { + unsafe.putOrderedInt(a, byte_offset(i), c); + unsafe.putOrderedInt(b, byte_offset(i+UNALIGN_OFF), d); + } + } + + static int verify(String text, int i, int elem, int val) { + if (elem != val) { + System.err.println(text + "[" + i + "] = " + elem + " != " + val); + return 1; + } + return 0; + } +} diff -r a413bcd552a4 -r 5fc51c1ecdeb test/compiler/8004867/TestIntUnsafeVolatile.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/8004867/TestIntUnsafeVolatile.java Tue Mar 05 23:44:54 2013 +0100 @@ -0,0 +1,990 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/** + * @test + * @bug 8004867 + * @summary VM crashing with assert "share/vm/opto/node.hpp:357 - assert(i < _max) failed: oob" + * + * @run main/othervm/timeout=300 -Xbatch -XX:+IgnoreUnrecognizedVMOptions -XX:-TieredCompilation -XX:-OptimizeFill TestIntUnsafeVolatile + * @run main/othervm/timeout=300 -Xbatch -XX:+IgnoreUnrecognizedVMOptions -XX:-TieredCompilation -XX:+OptimizeFill TestIntUnsafeVolatile + */ + +import sun.misc.Unsafe; +import java.lang.reflect.*; + +public class TestIntUnsafeVolatile { + private static final int ARRLEN = 97; + private static final int ITERS = 11000; + private static final int OFFSET = 3; + private static final int SCALE = 2; + private static final int ALIGN_OFF = 8; + private static final int UNALIGN_OFF = 5; + + private static final Unsafe unsafe; + private static final int BASE; + static { + try { + Class c = TestIntUnsafeVolatile.class.getClassLoader().loadClass("sun.misc.Unsafe"); + Field f = c.getDeclaredField("theUnsafe"); + f.setAccessible(true); + unsafe = (Unsafe)f.get(c); + BASE = unsafe.arrayBaseOffset(int[].class); + } catch (Exception e) { + InternalError err = new InternalError(); + err.initCause(e); + throw err; + } + } + + public static void main(String args[]) { + System.out.println("Testing Integer array unsafe volatile operations"); + int errn = test(false); + if (errn > 0) { + System.err.println("FAILED: " + errn + " errors"); + System.exit(97); + } + System.out.println("PASSED"); + } + + static int test(boolean test_only) { + int[] a1 = new int[ARRLEN]; + int[] a2 = new int[ARRLEN]; + // Initialize + for (int i=0; i 0 || test_only) + return errn; + + // Initialize + for (int i=0; i= 0; i-=1) { + unsafe.putIntVolatile(a, byte_offset(i), -123); + } + } + static void test_vi_neg(int[] a, int b, int old) { + for (int i = ARRLEN-1; i >= 0; i-=1) { + unsafe.putIntVolatile(a, byte_offset(i), b); + } + } + static void test_cp_neg(int[] a, int[] b) { + for (int i = ARRLEN-1; i >= 0; i-=1) { + unsafe.putIntVolatile(a, byte_offset(i), b[i]); + } + } + static void test_2ci_neg(int[] a, int[] b) { + for (int i = ARRLEN-1; i >= 0; i-=1) { + unsafe.putIntVolatile(a, byte_offset(i), -123); + unsafe.putIntVolatile(b, byte_offset(i), -103); + } + } + static void test_2vi_neg(int[] a, int[] b, int c, int d) { + for (int i = ARRLEN-1; i >= 0; i-=1) { + unsafe.putIntVolatile(a, byte_offset(i), c); + unsafe.putIntVolatile(b, byte_offset(i), d); + } + } + static void test_ci_oppos(int[] a, int old) { + int limit = ARRLEN-1; + for (int i = 0; i < ARRLEN; i+=1) { + unsafe.putIntVolatile(a, byte_offset(limit-i), -123); + } + } + static void test_vi_oppos(int[] a, int b, int old) { + int limit = ARRLEN-1; + for (int i = limit; i >= 0; i-=1) { + unsafe.putIntVolatile(a, byte_offset(limit-i), b); + } + } + static void test_cp_oppos(int[] a, int[] b) { + int limit = ARRLEN-1; + for (int i = 0; i < ARRLEN; i+=1) { + unsafe.putIntVolatile(a, byte_offset(i), b[limit-i]); + } + } + static void test_2ci_oppos(int[] a, int[] b) { + int limit = ARRLEN-1; + for (int i = 0; i < ARRLEN; i+=1) { + unsafe.putIntVolatile(a, byte_offset(limit-i), -123); + unsafe.putIntVolatile(b, byte_offset(i), -103); + } + } + static void test_2vi_oppos(int[] a, int[] b, int c, int d) { + int limit = ARRLEN-1; + for (int i = limit; i >= 0; i-=1) { + unsafe.putIntVolatile(a, byte_offset(i), c); + unsafe.putIntVolatile(b, byte_offset(limit-i), d); + } + } + static void test_ci_off(int[] a, int old) { + for (int i = 0; i < ARRLEN-OFFSET; i+=1) { + unsafe.putIntVolatile(a, byte_offset(i+OFFSET), -123); + } + } + static void test_vi_off(int[] a, int b, int old) { + for (int i = 0; i < ARRLEN-OFFSET; i+=1) { + unsafe.putIntVolatile(a, byte_offset(i+OFFSET), b); + } + } + static void test_cp_off(int[] a, int[] b) { + for (int i = 0; i < ARRLEN-OFFSET; i+=1) { + unsafe.putIntVolatile(a, byte_offset(i+OFFSET), b[i+OFFSET]); + } + } + static void test_2ci_off(int[] a, int[] b) { + for (int i = 0; i < ARRLEN-OFFSET; i+=1) { + unsafe.putIntVolatile(a, byte_offset(i+OFFSET), -123); + unsafe.putIntVolatile(b, byte_offset(i+OFFSET), -103); + } + } + static void test_2vi_off(int[] a, int[] b, int c, int d) { + for (int i = 0; i < ARRLEN-OFFSET; i+=1) { + unsafe.putIntVolatile(a, byte_offset(i+OFFSET), c); + unsafe.putIntVolatile(b, byte_offset(i+OFFSET), d); + } + } + static void test_ci_inv(int[] a, int k, int old) { + for (int i = 0; i < ARRLEN-k; i+=1) { + unsafe.putIntVolatile(a, byte_offset(i+k), -123); + } + } + static void test_vi_inv(int[] a, int b, int k, int old) { + for (int i = 0; i < ARRLEN-k; i+=1) { + unsafe.putIntVolatile(a, byte_offset(i+k), b); + } + } + static void test_cp_inv(int[] a, int[] b, int k) { + for (int i = 0; i < ARRLEN-k; i+=1) { + unsafe.putIntVolatile(a, byte_offset(i+k), b[i+k]); + } + } + static void test_2ci_inv(int[] a, int[] b, int k) { + for (int i = 0; i < ARRLEN-k; i+=1) { + unsafe.putIntVolatile(a, byte_offset(i+k), -123); + unsafe.putIntVolatile(b, byte_offset(i+k), -103); + } + } + static void test_2vi_inv(int[] a, int[] b, int c, int d, int k) { + for (int i = 0; i < ARRLEN-k; i+=1) { + unsafe.putIntVolatile(a, byte_offset(i+k), c); + unsafe.putIntVolatile(b, byte_offset(i+k), d); + } + } + static void test_ci_scl(int[] a, int old) { + for (int i = 0; i*SCALE < ARRLEN; i+=1) { + unsafe.putIntVolatile(a, byte_offset(i*SCALE), -123); + } + } + static void test_vi_scl(int[] a, int b, int old) { + for (int i = 0; i*SCALE < ARRLEN; i+=1) { + unsafe.putIntVolatile(a, byte_offset(i*SCALE), b); + } + } + static void test_cp_scl(int[] a, int[] b) { + for (int i = 0; i*SCALE < ARRLEN; i+=1) { + unsafe.putIntVolatile(a, byte_offset(i*SCALE), b[i*SCALE]); + } + } + static void test_2ci_scl(int[] a, int[] b) { + for (int i = 0; i*SCALE < ARRLEN; i+=1) { + unsafe.putIntVolatile(a, byte_offset(i*SCALE), -123); + unsafe.putIntVolatile(b, byte_offset(i*SCALE), -103); + } + } + static void test_2vi_scl(int[] a, int[] b, int c, int d) { + for (int i = 0; i*SCALE < ARRLEN; i+=1) { + unsafe.putIntVolatile(a, byte_offset(i*SCALE), c); + unsafe.putIntVolatile(b, byte_offset(i*SCALE), d); + } + } + static void test_cp_alndst(int[] a, int[] b) { + for (int i = 0; i < ARRLEN-ALIGN_OFF; i+=1) { + unsafe.putIntVolatile(a, byte_offset(i+ALIGN_OFF), b[i]); + } + } + static void test_cp_alnsrc(int[] a, int[] b) { + for (int i = 0; i < ARRLEN-ALIGN_OFF; i+=1) { + unsafe.putIntVolatile(a, byte_offset(i), b[i+ALIGN_OFF]); + } + } + static void test_2ci_aln(int[] a, int[] b) { + for (int i = 0; i < ARRLEN-ALIGN_OFF; i+=1) { + unsafe.putIntVolatile(a, byte_offset(i+ALIGN_OFF), -123); + unsafe.putIntVolatile(b, byte_offset(i), -103); + } + } + static void test_2vi_aln(int[] a, int[] b, int c, int d) { + for (int i = 0; i < ARRLEN-ALIGN_OFF; i+=1) { + unsafe.putIntVolatile(a, byte_offset(i), c); + unsafe.putIntVolatile(b, byte_offset(i+ALIGN_OFF), d); + } + } + static void test_cp_unalndst(int[] a, int[] b) { + for (int i = 0; i < ARRLEN-UNALIGN_OFF; i+=1) { + unsafe.putIntVolatile(a, byte_offset(i+UNALIGN_OFF), b[i]); + } + } + static void test_cp_unalnsrc(int[] a, int[] b) { + for (int i = 0; i < ARRLEN-UNALIGN_OFF; i+=1) { + unsafe.putIntVolatile(a, byte_offset(i), b[i+UNALIGN_OFF]); + } + } + static void test_2ci_unaln(int[] a, int[] b) { + for (int i = 0; i < ARRLEN-UNALIGN_OFF; i+=1) { + unsafe.putIntVolatile(a, byte_offset(i+UNALIGN_OFF), -123); + unsafe.putIntVolatile(b, byte_offset(i), -103); + } + } + static void test_2vi_unaln(int[] a, int[] b, int c, int d) { + for (int i = 0; i < ARRLEN-UNALIGN_OFF; i+=1) { + unsafe.putIntVolatile(a, byte_offset(i), c); + unsafe.putIntVolatile(b, byte_offset(i+UNALIGN_OFF), d); + } + } + + static int verify(String text, int i, int elem, int val) { + if (elem != val) { + System.err.println(text + "[" + i + "] = " + elem + " != " + val); + return 1; + } + return 0; + } +} diff -r a413bcd552a4 -r 5fc51c1ecdeb test/compiler/8007294/Test8007294.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/8007294/Test8007294.java Tue Mar 05 23:44:54 2013 +0100 @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8007294 + * @summary ReduceFieldZeroing doesn't check for dependent load and can lead to incorrect execution + * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+AlwaysIncrementalInline -XX:-UseOnStackReplacement -XX:-BackgroundCompilation Test8007294 + * + */ + +public class Test8007294 { + + int i1; + int i2; + + Test8007294(int i1, int i2) { + this.i1 = i1; + this.i2 = i2; + } + + static int m(int v) { + return v; + } + + static Test8007294 test1() { + Test8007294 obj = new Test8007294(10, 100); + int v1 = obj.i1; + + int v3 = m(v1); + int v2 = obj.i2; + obj.i2 = v3; + obj.i1 = v2; + + return obj; + } + + static int test2(int i) { + int j = 0; + if (i > 0) { + j = 1; + } + + int[] arr = new int[10]; + arr[0] = 1; + arr[1] = 2; + int v1 = arr[j]; + arr[0] = 3; + arr[1] = 4; + + return v1; + } + + static public void main(String[] args) { + boolean failed = false; + for (int i = 0; i < 20000; i++) { + Test8007294 obj = test1(); + if (obj.i1 != 100 || obj.i2 != 10) { + System.out.println("FAILED test1 obj.i1 = " + obj.i1 +", obj.i2 = " + obj.i2); + failed = true; + break; + } + } + for (int i = 0; i < 20000; i++) { + int res = test2(1); + if (res != 2) { + System.out.println("FAILED test2 = " + res); + failed = true; + break; + } + } + if (failed) { + System.exit(97); + } else { + System.out.println("PASSED"); + } + } +} diff -r a413bcd552a4 -r 5fc51c1ecdeb test/compiler/8007722/Test8007722.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/8007722/Test8007722.java Tue Mar 05 23:44:54 2013 +0100 @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8007722 + * @summary GetAndSetP's MachNode should capture bottom type + * @run main/othervm -XX:-UseOnStackReplacement -XX:-BackgroundCompilation Test8007722 + * + */ + +import java.util.concurrent.atomic.*; + +public class Test8007722 { + + int i; + static AtomicReference ref; + + static int test(Test8007722 new_obj) { + Test8007722 o = ref.getAndSet(new_obj); + int ret = o.i; + o.i = 5; + return ret; + } + + static public void main(String[] args) { + Test8007722 obj = new Test8007722(); + ref = new AtomicReference(obj); + + for (int i = 0; i < 20000; i++) { + test(obj); + } + + System.out.println("PASSED"); + } +} diff -r a413bcd552a4 -r 5fc51c1ecdeb test/compiler/whitebox/CompilerWhiteBoxTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/whitebox/CompilerWhiteBoxTest.java Tue Mar 05 23:44:54 2013 +0100 @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import sun.hotspot.WhiteBox; +import sun.management.ManagementFactoryHelper; +import com.sun.management.HotSpotDiagnosticMXBean; + +import java.lang.reflect.Method; + +/* + * @author igor.ignatyev@oracle.com + */ +public abstract class CompilerWhiteBoxTest { + protected static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox(); + protected static final Method METHOD = getMethod("method"); + protected static final int COMPILE_THRESHOLD + = Integer.parseInt(getVMOption("CompileThreshold", "10000")); + + protected static Method getMethod(String name) { + try { + return CompilerWhiteBoxTest.class.getDeclaredMethod(name); + } catch (NoSuchMethodException | SecurityException e) { + throw new RuntimeException( + "exception on getting method " + name, e); + } + } + + protected static String getVMOption(String name, String defaultValue) { + String result; + HotSpotDiagnosticMXBean diagnostic + = ManagementFactoryHelper.getDiagnosticMXBean(); + result = diagnostic.getVMOption(name).getValue(); + return result == null ? defaultValue : result; + } + + protected final void runTest() throws RuntimeException { + if (ManagementFactoryHelper.getCompilationMXBean() == null) { + System.err.println( + "Warning: test is not applicable in interpreted mode"); + return; + } + System.out.println("at test's start:"); + printInfo(METHOD); + try { + test(); + } catch (Exception e) { + System.out.printf("on exception '%s':", e.getMessage()); + printInfo(METHOD); + throw new RuntimeException(e); + } + System.out.println("at test's end:"); + printInfo(METHOD); + } + + protected static void checkNotCompiled(Method method) { + if (WHITE_BOX.isMethodCompiled(method)) { + throw new RuntimeException(method + " must be not compiled"); + } + if (WHITE_BOX.getMethodCompilationLevel(method) != 0) { + throw new RuntimeException(method + " comp_level must be == 0"); + } + } + + protected static void checkCompiled(Method method) + throws InterruptedException { + final long start = System.currentTimeMillis(); + waitBackgroundCompilation(method); + if (WHITE_BOX.isMethodQueuedForCompilation(method)) { + System.err.printf("Warning: %s is still in queue after %dms%n", + method, System.currentTimeMillis() - start); + return; + } + if (!WHITE_BOX.isMethodCompiled(method)) { + throw new RuntimeException(method + " must be compiled"); + } + if (WHITE_BOX.getMethodCompilationLevel(method) == 0) { + throw new RuntimeException(method + " comp_level must be != 0"); + } + } + + protected static void waitBackgroundCompilation(Method method) + throws InterruptedException { + final Object obj = new Object(); + synchronized (obj) { + for (int i = 0; i < 10; ++i) { + if (!WHITE_BOX.isMethodQueuedForCompilation(method)) { + break; + } + obj.wait(1000); + } + } + } + + protected static void printInfo(Method method) { + System.out.printf("%n%s:%n", method); + System.out.printf("\tcompilable:\t%b%n", + WHITE_BOX.isMethodCompilable(method)); + System.out.printf("\tcompiled:\t%b%n", + WHITE_BOX.isMethodCompiled(method)); + System.out.printf("\tcomp_level:\t%d%n", + WHITE_BOX.getMethodCompilationLevel(method)); + System.out.printf("\tin_queue:\t%b%n", + WHITE_BOX.isMethodQueuedForCompilation(method)); + System.out.printf("compile_queues_size:\t%d%n%n", + WHITE_BOX.getCompileQueuesSize()); + } + + protected abstract void test() throws Exception; + + protected final int compile() { + int result = 0; + for (int i = 0; i < COMPILE_THRESHOLD; ++i) { + result += method(); + } + return result; + } + + + protected int method() { + return 42; + } +} diff -r a413bcd552a4 -r 5fc51c1ecdeb test/compiler/whitebox/DeoptimizeAllTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/whitebox/DeoptimizeAllTest.java Tue Mar 05 23:44:54 2013 +0100 @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test DeoptimizeAllTest + * @library /testlibrary /testlibrary/whitebox + * @build DeoptimizeAllTest + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI DeoptimizeAllTest + * @author igor.ignatyev@oracle.com + */ +public class DeoptimizeAllTest extends CompilerWhiteBoxTest { + + public static void main(String[] args) throws Exception { + new DeoptimizeAllTest().runTest(); + } + + protected void test() throws Exception { + // to prevent inlining #method into #compile() + WHITE_BOX.setDontInlineMethod(METHOD, true); + compile(); + checkCompiled(METHOD); + WHITE_BOX.deoptimizeAll(); + checkNotCompiled(METHOD); + } +} diff -r a413bcd552a4 -r 5fc51c1ecdeb test/compiler/whitebox/DeoptimizeMethodTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/whitebox/DeoptimizeMethodTest.java Tue Mar 05 23:44:54 2013 +0100 @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test DeoptimizeMethodTest + * @library /testlibrary /testlibrary/whitebox + * @build DeoptimizeMethodTest + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI DeoptimizeMethodTest + * @author igor.ignatyev@oracle.com + */ +public class DeoptimizeMethodTest extends CompilerWhiteBoxTest { + + public static void main(String[] args) throws Exception { + new DeoptimizeMethodTest().runTest(); + } + + protected void test() throws Exception { + // to prevent inlining #method into #compile() + WHITE_BOX.setDontInlineMethod(METHOD, true); + compile(); + checkCompiled(METHOD); + WHITE_BOX.deoptimizeMethod(METHOD); + checkNotCompiled(METHOD); + } +} diff -r a413bcd552a4 -r 5fc51c1ecdeb test/compiler/whitebox/IsMethodCompilableTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/whitebox/IsMethodCompilableTest.java Tue Mar 05 23:44:54 2013 +0100 @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test IsMethodCompilableTest + * @bug 8007270 + * @library /testlibrary /testlibrary/whitebox + * @build IsMethodCompilableTest + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm/timeout=600 -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI IsMethodCompilableTest + * @author igor.ignatyev@oracle.com + */ +public class IsMethodCompilableTest extends CompilerWhiteBoxTest { + protected static final long PER_METHOD_RECOMPILATION_CUTOFF; + + static { + long tmp = Long.parseLong( + getVMOption("PerMethodRecompilationCutoff", "400")); + if (tmp == -1) { + PER_METHOD_RECOMPILATION_CUTOFF = -1 /* Inf */; + } else { + PER_METHOD_RECOMPILATION_CUTOFF = 1 + (0xFFFFFFFFL & tmp); + } + } + + public static void main(String[] args) throws Exception { + new IsMethodCompilableTest().runTest(); + } + + protected void test() throws Exception { + if (!WHITE_BOX.isMethodCompilable(METHOD)) { + throw new RuntimeException(METHOD + " must be compilable"); + } + System.out.println("PerMethodRecompilationCutoff = " + + PER_METHOD_RECOMPILATION_CUTOFF); + if (PER_METHOD_RECOMPILATION_CUTOFF == -1) { + System.err.println( + "Warning: test is not applicable if PerMethodRecompilationCutoff == Inf"); + return; + } + // to prevent inlining #method into #compile() + WHITE_BOX.setDontInlineMethod(METHOD, true); + boolean madeNotCompilable = false; + + for (long i = 0; i < PER_METHOD_RECOMPILATION_CUTOFF; ++i) { + compile(); + waitBackgroundCompilation(METHOD); + WHITE_BOX.deoptimizeMethod(METHOD); + if (!WHITE_BOX.isMethodCompilable(METHOD)) { + madeNotCompilable = true; + break; + } + } + if (!madeNotCompilable) { + throw new RuntimeException(METHOD + " is still compilable after " + + PER_METHOD_RECOMPILATION_CUTOFF + " iterations"); + } + compile(); + if (WHITE_BOX.isMethodCompiled(METHOD)) { + printInfo(METHOD); + throw new RuntimeException( + METHOD + " is not compilable but compiled"); + } + } +} diff -r a413bcd552a4 -r 5fc51c1ecdeb test/compiler/whitebox/MakeMethodNotCompilableTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/whitebox/MakeMethodNotCompilableTest.java Tue Mar 05 23:44:54 2013 +0100 @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test MakeMethodNotCompilableTest + * @library /testlibrary /testlibrary/whitebox + * @build MakeMethodNotCompilableTest + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI MakeMethodNotCompilableTest + * @author igor.ignatyev@oracle.com + */ +public class MakeMethodNotCompilableTest extends CompilerWhiteBoxTest { + + public static void main(String[] args) throws Exception { + new MakeMethodNotCompilableTest().runTest(); + } + + protected void test() throws Exception { + if (!WHITE_BOX.isMethodCompilable(METHOD)) { + throw new RuntimeException(METHOD + " must be compilable"); + } + WHITE_BOX.makeMethodNotCompilable(METHOD); + if (WHITE_BOX.isMethodCompilable(METHOD)) { + throw new RuntimeException(METHOD + " must be not compilable"); + } + compile(); + if (WHITE_BOX.isMethodQueuedForCompilation(METHOD)) { + throw new RuntimeException(METHOD + " must not be in queue"); + } + checkNotCompiled(METHOD); + if (WHITE_BOX.isMethodCompilable(METHOD)) { + throw new RuntimeException(METHOD + " must be not compilable"); + } + } +} diff -r a413bcd552a4 -r 5fc51c1ecdeb test/compiler/whitebox/SetDontInlineMethodTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/whitebox/SetDontInlineMethodTest.java Tue Mar 05 23:44:54 2013 +0100 @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test SetDontInlineMethodTest + * @library /testlibrary /testlibrary/whitebox + * @build SetDontInlineMethodTest + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI SetDontInlineMethodTest + * @author igor.ignatyev@oracle.com + */ +public class SetDontInlineMethodTest extends CompilerWhiteBoxTest { + + public static void main(String[] args) throws Exception { + new SetDontInlineMethodTest().runTest(); + } + + protected void test() throws Exception { + if (WHITE_BOX.setDontInlineMethod(METHOD, true)) { + throw new RuntimeException("on start " + METHOD + + " must be inlineable"); + } + if (!WHITE_BOX.setDontInlineMethod(METHOD, true)) { + throw new RuntimeException("after first change to true " + METHOD + + " must be not inlineable"); + } + if (!WHITE_BOX.setDontInlineMethod(METHOD, false)) { + throw new RuntimeException("after second change to true " + METHOD + + " must be still not inlineable"); + } + if (WHITE_BOX.setDontInlineMethod(METHOD, false)) { + throw new RuntimeException("after first change to false" + METHOD + + " must be inlineable"); + } + if (WHITE_BOX.setDontInlineMethod(METHOD, false)) { + throw new RuntimeException("after second change to false " + METHOD + + " must be inlineable"); + } + } +} diff -r a413bcd552a4 -r 5fc51c1ecdeb test/gc/8000311/Test8000311.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/gc/8000311/Test8000311.java Tue Mar 05 23:44:54 2013 +0100 @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test Test8000311 + * @key gc + * @bug 8000311 + * @summary G1: ParallelGCThreads==0 broken + * @run main/othervm -XX:+UseG1GC -XX:ParallelGCThreads=0 -XX:+ResizePLAB -XX:+ExplicitGCInvokesConcurrent Test8000311 + * @author filipp.zhinkin@oracle.com + */ + +import java.util.*; + +public class Test8000311 { + public static void main(String args[]) { + for(int i = 0; i<100; i++) { + byte[] garbage = new byte[1000]; + System.gc(); + } + } +} diff -r a413bcd552a4 -r 5fc51c1ecdeb test/gc/TestG1ZeroPGCTJcmdThreadPrint.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/gc/TestG1ZeroPGCTJcmdThreadPrint.java Tue Mar 05 23:44:54 2013 +0100 @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* @test TestG1ZeroPGCTJcmdThreadPrint + * @key gc + * @bug 8005875 + * @summary Use jcmd to generate a thread dump of a Java program being run with PGCT=0 to verify 8005875 + * @library /testlibrary + * @run main/othervm -XX:+UseG1GC -XX:ParallelGCThreads=0 -XX:+IgnoreUnrecognizedVMOptions TestG1ZeroPGCTJcmdThreadPrint + */ + +import com.oracle.java.testlibrary.*; + +public class TestG1ZeroPGCTJcmdThreadPrint { + public static void main(String args[]) throws Exception { + + // Grab the pid from the current java process + String pid = Integer.toString(ProcessTools.getProcessId()); + + // Create a ProcessBuilder + ProcessBuilder pb = new ProcessBuilder(); + + // Run jcmd Thread.print + pb.command(JDKToolFinder.getJDKTool("jcmd"), pid, "Thread.print"); + + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + + // There shouldn't be a work gang for concurrent marking. + output.shouldNotContain("G1 Parallel Marking Threads"); + + // Make sure we didn't crash + output.shouldHaveExitValue(0); + } +} diff -r a413bcd552a4 -r 5fc51c1ecdeb test/gc/metaspace/ClassMetaspaceSizeInJmapHeap.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/gc/metaspace/ClassMetaspaceSizeInJmapHeap.java Tue Mar 05 23:44:54 2013 +0100 @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test ClassMetaspaceSizeInJmapHeap + * @bug 8004924 + * @summary Checks that jmap -heap contains the flag ClassMetaspaceSize + * @library /testlibrary + * @run main/othervm -XX:ClassMetaspaceSize=50m ClassMetaspaceSizeInJmapHeap + */ + +import com.oracle.java.testlibrary.*; +import java.nio.file.*; +import java.io.File; +import java.nio.charset.Charset; +import java.util.List; + +public class ClassMetaspaceSizeInJmapHeap { + public static void main(String[] args) throws Exception { + String pid = Integer.toString(ProcessTools.getProcessId()); + + ProcessBuilder pb = new ProcessBuilder(); + pb.command(JDKToolFinder.getJDKTool("jmap"), "-heap", pid); + + File out = new File("ClassMetaspaceSizeInJmapHeap.stdout.txt"); + pb.redirectOutput(out); + + File err = new File("ClassMetaspaceSizeInJmapHeap.stderr.txt"); + pb.redirectError(err); + + run(pb); + + OutputAnalyzer output = new OutputAnalyzer(read(out)); + output.shouldContain("ClassMetaspaceSize = 52428800 (50.0MB)"); + out.delete(); + } + + private static void run(ProcessBuilder pb) throws Exception { + Process p = pb.start(); + p.waitFor(); + int exitValue = p.exitValue(); + if (exitValue != 0) { + throw new Exception("jmap -heap exited with error code: " + exitValue); + } + } + + private static String read(File f) throws Exception { + Path p = f.toPath(); + List lines = Files.readAllLines(p, Charset.defaultCharset()); + + StringBuilder sb = new StringBuilder(); + for (String line : lines) { + sb.append(line).append('\n'); + } + return sb.toString(); + } +} diff -r a413bcd552a4 -r 5fc51c1ecdeb test/gc/startup_warnings/TestCMS.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/gc/startup_warnings/TestCMS.java Tue Mar 05 23:44:54 2013 +0100 @@ -0,0 +1,46 @@ +/* +* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* This code is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License version 2 only, as +* published by the Free Software Foundation. +* +* This code is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +* version 2 for more details (a copy is included in the LICENSE file that +* accompanied this code). +* +* You should have received a copy of the GNU General Public License version +* 2 along with this work; if not, write to the Free Software Foundation, +* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +* +* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +* or visit www.oracle.com if you need additional information or have any +* questions. +*/ + +/* +* @test TestCMS +* @key gc +* @bug 8006398 +* @summary Test that CMS does not print a warning message +* @library /testlibrary +*/ + +import com.oracle.java.testlibrary.OutputAnalyzer; +import com.oracle.java.testlibrary.ProcessTools; + + +public class TestCMS { + + public static void main(String args[]) throws Exception { + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-XX:+UseConcMarkSweepGC", "-version"); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldNotContain("warning"); + output.shouldNotContain("error"); + output.shouldHaveExitValue(0); + } + +} diff -r a413bcd552a4 -r 5fc51c1ecdeb test/gc/startup_warnings/TestCMSIncrementalMode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/gc/startup_warnings/TestCMSIncrementalMode.java Tue Mar 05 23:44:54 2013 +0100 @@ -0,0 +1,46 @@ + +/* +* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* This code is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License version 2 only, as +* published by the Free Software Foundation. +* +* This code is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +* version 2 for more details (a copy is included in the LICENSE file that +* accompanied this code). +* +* You should have received a copy of the GNU General Public License version +* 2 along with this work; if not, write to the Free Software Foundation, +* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +* +* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +* or visit www.oracle.com if you need additional information or have any +* questions. +*/ + +/* +* @test TestCMSIncrementalMode +* @key gc +* @bug 8006398 +* @summary Test that the deprecated CMSIncrementalMode print a warning message +* @library /testlibrary +*/ + +import com.oracle.java.testlibrary.OutputAnalyzer; +import com.oracle.java.testlibrary.ProcessTools; + +public class TestCMSIncrementalMode { + + public static void main(String args[]) throws Exception { + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-XX:+UseConcMarkSweepGC", "-XX:+CMSIncrementalMode", "-version"); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldContain("warning: Using incremental CMS is deprecated and will likely be removed in a future release"); + output.shouldNotContain("error"); + output.shouldHaveExitValue(0); + } + +} diff -r a413bcd552a4 -r 5fc51c1ecdeb test/gc/startup_warnings/TestCMSNoIncrementalMode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/gc/startup_warnings/TestCMSNoIncrementalMode.java Tue Mar 05 23:44:54 2013 +0100 @@ -0,0 +1,45 @@ +/* +* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* This code is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License version 2 only, as +* published by the Free Software Foundation. +* +* This code is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +* version 2 for more details (a copy is included in the LICENSE file that +* accompanied this code). +* +* You should have received a copy of the GNU General Public License version +* 2 along with this work; if not, write to the Free Software Foundation, +* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +* +* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +* or visit www.oracle.com if you need additional information or have any +* questions. +*/ + +/* +* @test TestCMSNoIncrementalMode +* @key gc +* @bug 8006398 +* @summary Test that CMS with incremental mode turned off does not print a warning message +* @library /testlibrary +*/ + +import com.oracle.java.testlibrary.OutputAnalyzer; +import com.oracle.java.testlibrary.ProcessTools; + +public class TestCMSNoIncrementalMode { + + public static void main(String args[]) throws Exception { + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-XX:+UseConcMarkSweepGC", "-XX:-CMSIncrementalMode", "-version"); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldNotContain("warning"); + output.shouldNotContain("error"); + output.shouldHaveExitValue(0); + } + +} diff -r a413bcd552a4 -r 5fc51c1ecdeb test/gc/startup_warnings/TestDefNewCMS.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/gc/startup_warnings/TestDefNewCMS.java Tue Mar 05 23:44:54 2013 +0100 @@ -0,0 +1,45 @@ +/* +* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* This code is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License version 2 only, as +* published by the Free Software Foundation. +* +* This code is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +* version 2 for more details (a copy is included in the LICENSE file that +* accompanied this code). +* +* You should have received a copy of the GNU General Public License version +* 2 along with this work; if not, write to the Free Software Foundation, +* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +* +* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +* or visit www.oracle.com if you need additional information or have any +* questions. +*/ + +/* +* @test TestDefNewCMS +* @key gc +* @bug 8006398 +* @summary Test that the deprecated DefNew+CMS combination print a warning message +* @library /testlibrary +*/ + +import com.oracle.java.testlibrary.OutputAnalyzer; +import com.oracle.java.testlibrary.ProcessTools; + +public class TestDefNewCMS { + + public static void main(String args[]) throws Exception { + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-XX:-UseParNewGC", "-XX:+UseConcMarkSweepGC", "-version"); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldContain("warning: Using the DefNew young collector with the CMS collector is deprecated and will likely be removed in a future release"); + output.shouldNotContain("error"); + output.shouldHaveExitValue(0); + } + +} diff -r a413bcd552a4 -r 5fc51c1ecdeb test/gc/startup_warnings/TestG1.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/gc/startup_warnings/TestG1.java Tue Mar 05 23:44:54 2013 +0100 @@ -0,0 +1,45 @@ +/* +* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* This code is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License version 2 only, as +* published by the Free Software Foundation. +* +* This code is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +* version 2 for more details (a copy is included in the LICENSE file that +* accompanied this code). +* +* You should have received a copy of the GNU General Public License version +* 2 along with this work; if not, write to the Free Software Foundation, +* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +* +* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +* or visit www.oracle.com if you need additional information or have any +* questions. +*/ + +/* +* @test TestG1 +* @key gc +* @bug 8006398 +* @summary Test that the G1 collector does not print a warning message +* @library /testlibrary +*/ + +import com.oracle.java.testlibrary.OutputAnalyzer; +import com.oracle.java.testlibrary.ProcessTools; + +public class TestG1 { + + public static void main(String args[]) throws Exception { + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-XX:+UseG1GC", "-version"); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldNotContain("warning"); + output.shouldNotContain("error"); + output.shouldHaveExitValue(0); + } + +} diff -r a413bcd552a4 -r 5fc51c1ecdeb test/gc/startup_warnings/TestIncGC.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/gc/startup_warnings/TestIncGC.java Tue Mar 05 23:44:54 2013 +0100 @@ -0,0 +1,46 @@ +/* +* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* This code is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License version 2 only, as +* published by the Free Software Foundation. +* +* This code is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +* version 2 for more details (a copy is included in the LICENSE file that +* accompanied this code). +* +* You should have received a copy of the GNU General Public License version +* 2 along with this work; if not, write to the Free Software Foundation, +* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +* +* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +* or visit www.oracle.com if you need additional information or have any +* questions. +*/ + +/* +* @test TestIncGC +* @key gc +* @bug 8006398 +* @summary Test that the deprecated -Xincgc print a warning message +* @library /testlibrary +*/ + +import com.oracle.java.testlibrary.OutputAnalyzer; +import com.oracle.java.testlibrary.ProcessTools; + + +public class TestIncGC { + + public static void main(String args[]) throws Exception { + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-Xincgc", "-version"); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldContain("warning: Using incremental CMS is deprecated and will likely be removed in a future release"); + output.shouldNotContain("error"); + output.shouldHaveExitValue(0); + } + +} diff -r a413bcd552a4 -r 5fc51c1ecdeb test/gc/startup_warnings/TestParNewCMS.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/gc/startup_warnings/TestParNewCMS.java Tue Mar 05 23:44:54 2013 +0100 @@ -0,0 +1,46 @@ +/* +* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* This code is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License version 2 only, as +* published by the Free Software Foundation. +* +* This code is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +* version 2 for more details (a copy is included in the LICENSE file that +* accompanied this code). +* +* You should have received a copy of the GNU General Public License version +* 2 along with this work; if not, write to the Free Software Foundation, +* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +* +* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +* or visit www.oracle.com if you need additional information or have any +* questions. +*/ + +/* +* @test TestParNewCMS +* @key gc +* @bug 8006398 +* @summary Test that the combination ParNew+CMS does not print a warning message +* @library /testlibrary +*/ + +import com.oracle.java.testlibrary.OutputAnalyzer; +import com.oracle.java.testlibrary.ProcessTools; + + +public class TestParNewCMS { + + public static void main(String args[]) throws Exception { + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-XX:+UseParNewGC", "-XX:+UseConcMarkSweepGC", "-version"); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldNotContain("warning"); + output.shouldNotContain("error"); + output.shouldHaveExitValue(0); + } + +} diff -r a413bcd552a4 -r 5fc51c1ecdeb test/gc/startup_warnings/TestParNewSerialOld.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/gc/startup_warnings/TestParNewSerialOld.java Tue Mar 05 23:44:54 2013 +0100 @@ -0,0 +1,46 @@ +/* +* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* This code is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License version 2 only, as +* published by the Free Software Foundation. +* +* This code is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +* version 2 for more details (a copy is included in the LICENSE file that +* accompanied this code). +* +* You should have received a copy of the GNU General Public License version +* 2 along with this work; if not, write to the Free Software Foundation, +* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +* +* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +* or visit www.oracle.com if you need additional information or have any +* questions. +*/ + +/* +* @test TestParNewSerialOld +* @key gc +* @bug 8006398 +* @summary Test that the deprecated ParNew+SerialOld combination print a warning message +* @library /testlibrary +*/ + +import com.oracle.java.testlibrary.OutputAnalyzer; +import com.oracle.java.testlibrary.ProcessTools; + + +public class TestParNewSerialOld { + + public static void main(String args[]) throws Exception { + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-XX:+UseParNewGC", "-version"); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldContain("warning: Using the ParNew young collector with the Serial old collector is deprecated and will likely be removed in a future release"); + output.shouldNotContain("error"); + output.shouldHaveExitValue(0); + } + +} diff -r a413bcd552a4 -r 5fc51c1ecdeb test/gc/startup_warnings/TestParallelGC.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/gc/startup_warnings/TestParallelGC.java Tue Mar 05 23:44:54 2013 +0100 @@ -0,0 +1,46 @@ +/* +* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* This code is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License version 2 only, as +* published by the Free Software Foundation. +* +* This code is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +* version 2 for more details (a copy is included in the LICENSE file that +* accompanied this code). +* +* You should have received a copy of the GNU General Public License version +* 2 along with this work; if not, write to the Free Software Foundation, +* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +* +* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +* or visit www.oracle.com if you need additional information or have any +* questions. +*/ + +/* +* @test TestParallelGC +* @key gc +* @bug 8006398 +* @summary Test that ParallelGC does not print a warning message +* @library /testlibrary +*/ + +import com.oracle.java.testlibrary.OutputAnalyzer; +import com.oracle.java.testlibrary.ProcessTools; + + +public class TestParallelGC { + + public static void main(String args[]) throws Exception { + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-XX:+UseParallelGC", "-version"); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldNotContain("warning"); + output.shouldNotContain("error"); + output.shouldHaveExitValue(0); + } + +} diff -r a413bcd552a4 -r 5fc51c1ecdeb test/gc/startup_warnings/TestParallelScavengeSerialOld.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/gc/startup_warnings/TestParallelScavengeSerialOld.java Tue Mar 05 23:44:54 2013 +0100 @@ -0,0 +1,46 @@ +/* +* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* This code is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License version 2 only, as +* published by the Free Software Foundation. +* +* This code is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +* version 2 for more details (a copy is included in the LICENSE file that +* accompanied this code). +* +* You should have received a copy of the GNU General Public License version +* 2 along with this work; if not, write to the Free Software Foundation, +* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +* +* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +* or visit www.oracle.com if you need additional information or have any +* questions. +*/ + +/* +* @test TestParallelScavengeSerialOld +* @key gc +* @bug 8006398 +* @summary Test that the ParallelScavenge+SerialOld combination does not print a warning message +* @library /testlibrary +*/ + +import com.oracle.java.testlibrary.OutputAnalyzer; +import com.oracle.java.testlibrary.ProcessTools; + + +public class TestParallelScavengeSerialOld { + + public static void main(String args[]) throws Exception { + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-XX:+UseParallelGC", "-XX:-UseParallelOldGC", "-version"); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldNotContain("warning"); + output.shouldNotContain("error"); + output.shouldHaveExitValue(0); + } + +} diff -r a413bcd552a4 -r 5fc51c1ecdeb test/gc/startup_warnings/TestSerialGC.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/gc/startup_warnings/TestSerialGC.java Tue Mar 05 23:44:54 2013 +0100 @@ -0,0 +1,46 @@ +/* +* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* This code is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License version 2 only, as +* published by the Free Software Foundation. +* +* This code is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +* version 2 for more details (a copy is included in the LICENSE file that +* accompanied this code). +* +* You should have received a copy of the GNU General Public License version +* 2 along with this work; if not, write to the Free Software Foundation, +* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +* +* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +* or visit www.oracle.com if you need additional information or have any +* questions. +*/ + +/* +* @test TestSerialGC +* @key gc +* @bug 8006398 +* @summary Test that SerialGC does not print a warning message +* @library /testlibrary +*/ + +import com.oracle.java.testlibrary.OutputAnalyzer; +import com.oracle.java.testlibrary.ProcessTools; + + +public class TestSerialGC { + + public static void main(String args[]) throws Exception { + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-XX:+UseSerialGC", "-version"); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldNotContain("warning"); + output.shouldNotContain("error"); + output.shouldHaveExitValue(0); + } + +} diff -r a413bcd552a4 -r 5fc51c1ecdeb test/runtime/7158988/FieldMonitor.java --- a/test/runtime/7158988/FieldMonitor.java Tue Mar 05 21:58:51 2013 +0100 +++ b/test/runtime/7158988/FieldMonitor.java Tue Mar 05 23:44:54 2013 +0100 @@ -24,8 +24,10 @@ /* * @test FieldMonitor.java * @bug 7158988 + * @key regression * @summary verify jvm does not crash while debugging - * @run shell TestFieldMonitor.sh + * @run compile TestPostFieldModification.java + * @run main/othervm FieldMonitor * @author axel.siebenborn@sap.com */ import java.io.BufferedReader; diff -r a413bcd552a4 -r 5fc51c1ecdeb test/runtime/7158988/TestFieldMonitor.sh --- a/test/runtime/7158988/TestFieldMonitor.sh Tue Mar 05 21:58:51 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,75 +0,0 @@ -#!/bin/sh - -if [ "${TESTSRC}" = "" ] -then TESTSRC=. -fi - -if [ "${TESTJAVA}" = "" ] -then - PARENT=`dirname \`which java\`` - TESTJAVA=`dirname ${PARENT}` - echo "TESTJAVA not set, selecting " ${TESTJAVA} - echo "If this is incorrect, try setting the variable manually." -fi - -if [ "${TESTCLASSES}" = "" ] -then - echo "TESTCLASSES not set. Test cannot execute. Failed." - exit 1 -fi - -# set platform-dependent variables -OS=`uname -s` -case "$OS" in - SunOS | Linux | Darwin) - NULL=/dev/null - PS=":" - FS="/" - ;; - Windows_95 | Windows_98 | Windows_ME ) - NULL=NUL - PS=";" - FS="\\" - echo "Test skipped, only for WinNT" - exit 0 - ;; - Windows_NT ) - NULL=NUL - PS=";" - FS="\\" - ;; - CYGWIN_NT* ) - NULL=/dev/null - PS=";" - FS="/" - ;; - CYGWIN_* ) - NULL=/dev/null - PS=";" - FS="/" - echo "Test skipped, only for WinNT" - exit 0 - ;; - * ) - echo "Unrecognized system!" - exit 1; - ;; -esac - -#CLASSPATH=.${PS}${TESTCLASSES} ; export CLASSPATH - -cp ${TESTSRC}${FS}*.java . - -${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} -fullversion - -${TESTJAVA}${FS}bin${FS}javac -classpath .${PS}$TESTJAVA${FS}lib${FS}tools.jar *.java - -${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} -classpath .${PS}$TESTJAVA${FS}lib${FS}tools.jar FieldMonitor > test.out - -grep "A fatal error has been detected" test.out > ${NULL} -if [ $? = 0 ]; then - cat test.out - STATUS=1 -fi - -exit $STATUS diff -r a413bcd552a4 -r 5fc51c1ecdeb test/runtime/8000968/Test8000968.sh --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/runtime/8000968/Test8000968.sh Tue Mar 05 23:44:54 2013 +0100 @@ -0,0 +1,99 @@ +# +# Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + + +# @test Test8000968.sh +# @bug 8000968 +# @summary NPG: UseCompressedKlassPointers asserts with ObjectAlignmentInBytes=32 +# @run shell Test8000968.sh +# + +if [ "${TESTJAVA}" = "" ] +then + PARENT=`dirname \`which java\`` + TESTJAVA=`dirname ${PARENT}` + printf "TESTJAVA not set, selecting " ${TESTJAVA} + printf " If this is incorrect, try setting the variable manually.\n" +fi + + +# set platform-dependent variables +OS=`uname -s` +case "$OS" in + Windows_* ) + FS="\\" + NULL=NUL + ;; + * ) + FS="/" + NULL=/dev/null + ;; +esac + +JAVA=${TESTJAVA}${FS}bin${FS}java + +# +# See if platform has 64 bit java. +# +${JAVA} ${TESTVMOPTS} -d64 -version 2>&1 | grep -i "does not support" > ${NULL} +if [ "$?" != "1" ] +then + printf "Platform is 32 bit, does not support -XX:ObjectAlignmentInBytes= option.\n" + printf "Passed.\n" + exit 0 +fi + +# +# Test -XX:ObjectAlignmentInBytes with -XX:+UseCompressedKlassPointers -XX:+UseCompressedOops. +# +${JAVA} ${TESTVMOPTS} -d64 -XX:+UseCompressedKlassPointers -XX:+UseCompressedOops -XX:ObjectAlignmentInBytes=16 -version 2>&1 > ${NULL} +if [ "$?" != "0" ] +then + printf "FAILED: -XX:ObjectAlignmentInBytes=16 option did not work.\n" + exit 1 +fi + +${JAVA} ${TESTVMOPTS} -d64 -XX:+UseCompressedKlassPointers -XX:+UseCompressedOops -XX:ObjectAlignmentInBytes=32 -version 2>&1 > ${NULL} +if [ "$?" != "0" ] +then + printf "FAILED: -XX:ObjectAlignmentInBytes=32 option did not work.\n" + exit 1 +fi + +${JAVA} ${TESTVMOPTS} -d64 -XX:+UseCompressedKlassPointers -XX:+UseCompressedOops -XX:ObjectAlignmentInBytes=64 -version 2>&1 > ${NULL} +if [ "$?" != "0" ] +then + printf "FAILED: -XX:ObjectAlignmentInBytes=64 option did not work.\n" + exit 1 +fi + +${JAVA} ${TESTVMOPTS} -d64 -XX:+UseCompressedKlassPointers -XX:+UseCompressedOops -XX:ObjectAlignmentInBytes=128 -version 2>&1 > ${NULL} +if [ "$?" != "0" ] +then + printf "FAILED: -XX:ObjectAlignmentInBytes=128 option did not work.\n" + exit 1 +fi + + +printf "Passed.\n" +exit 0 diff -r a413bcd552a4 -r 5fc51c1ecdeb test/runtime/8007320/ConstMethodTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/runtime/8007320/ConstMethodTest.java Tue Mar 05 23:44:54 2013 +0100 @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8007320 + * @summary Test all optional fields in ConstMethod + * @compile -g -parameters ConstMethodTest.java + * @run main ConstMethodTest + */ + +import java.util.*; +import java.lang.annotation.*; +import java.lang.reflect.*; +import java.io.Serializable; + +@Retention(RetentionPolicy.RUNTIME) +@interface MyAnnotation { + public String name(); + public String value(); + public String date() default "today"; +} + +@Target(ElementType.TYPE_USE) +@Retention(RetentionPolicy.RUNTIME) +@interface TypeAnno { + String value(); +} + +@Target(ElementType.TYPE_USE) +@Retention(RetentionPolicy.RUNTIME) +@interface TypeAnno2 { + String value(); +} + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.PARAMETER) +@interface Named { + String value(); +} + +@Retention(RetentionPolicy.RUNTIME) +@interface ScalarTypesWithDefault { + byte b() default 11; + short s() default 12; + int i() default 13; + long l() default 14; + char c() default 'V'; +} + +// Some exception class +class OkException extends RuntimeException {}; + + +@MyAnnotation(name="someName", value = "Hello World") +public class ConstMethodTest { + + private static void check(boolean b) { + if (!b) + throw new RuntimeException(); + } + private static void fail(String msg) { + System.err.println(msg); + throw new RuntimeException(); + } + private static void equal(Object x, Object y) { + if (x == null ? y == null : x.equals(y)) { + } else { + fail(x + " not equal to " + y); + } + } + private static final String[] parameter_names = { + "parameter", "parameter2", "x" + }; + + // Declare a function with everything in it. + @MyAnnotation(name="someName", value="Hello World") + static void kitchenSinkFunc(@Named(value="aName") String parameter, + @Named("bName") String parameter2, + @ScalarTypesWithDefault T x) + throws @TypeAnno("RE") @TypeAnno2("RE2") RuntimeException, + NullPointerException, + @TypeAnno("AIOOBE") ArrayIndexOutOfBoundsException { + int i, j, k; + try { + System.out.println("calling kitchenSinkFunc " + parameter); + throw new OkException(); // to see stack trace with line numbers + } catch (Exception e) { + e.printStackTrace(); + } + } + + private static void test1() throws Throwable { + for (Method m : ConstMethodTest.class.getDeclaredMethods()) { + if (m.getName().equals("kitchenSinkFunc")) { + Annotation[][] ann = m.getParameterAnnotations(); + equal(ann.length, 3); + Annotation foo = ann[0][0]; + Annotation bar = ann[1][0]; + equal(foo.toString(), "@Named(value=aName)"); + equal(bar.toString(), "@Named(value=bName)"); + check(foo.equals(foo)); + check(bar.equals(bar)); + check(! foo.equals(bar)); + // method annotations + Annotation[] ann2 = m.getAnnotations(); + equal(ann2.length, 1); + Annotation mann = ann2[0]; + equal(mann.toString(), "@MyAnnotation(date=today, name=someName, value=Hello World)"); + // Test Method parameter names + Parameter[] parameters = m.getParameters(); + if(parameters == null) + throw new Exception("getParameters should never be null"); + for(int i = 0; i < parameters.length; i++) { + Parameter p = parameters[i]; + equal(parameters[i].getName(), parameter_names[i]); + } + } + } + } + + public static void main(java.lang.String[] unused) throws Throwable { + // pass 5 so kitchenSinkFunc is instantiated with an int + kitchenSinkFunc("parameter", "param2", 5); + test1(); + } +}; + diff -r a413bcd552a4 -r 5fc51c1ecdeb test/runtime/8007475/StackMapFrameTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/runtime/8007475/StackMapFrameTest.java Tue Mar 05 23:44:54 2013 +0100 @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8007475 + * @summary Test memory stomp in stack map test + * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+UseMallocOnly StackMapFrameTest + */ +public class StackMapFrameTest { + + public static void foo() { + Object o = new Object(); + } + + public static void main(String args[]) { + for (int i = 0; i < 25000; i++) { + foo(); + } + } +} diff -r a413bcd552a4 -r 5fc51c1ecdeb test/runtime/8007736/TestStaticIF.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/runtime/8007736/TestStaticIF.java Tue Mar 05 23:44:54 2013 +0100 @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/* + * @test + * @bug 8007736 + * @summary Test static interface method. + * @run main/othervm -Xverify:all TestStaticIF + */ + +public class TestStaticIF implements StaticMethodInInterface { + + public static void main(String[] args) { + System.out.printf("main: %s%n", StaticMethodInInterface.get()); + } +} + +interface StaticMethodInInterface { + + public static String get() { + return "Hello from StaticMethodInInterface.get()"; + } +} diff -r a413bcd552a4 -r 5fc51c1ecdeb test/runtime/CommandLine/BooleanFlagWithInvalidValue.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/runtime/CommandLine/BooleanFlagWithInvalidValue.java Tue Mar 05 23:44:54 2013 +0100 @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8006298 + * @summary Setting an invalid value for a bool argument should result in a useful error message + * @library /testlibrary + */ + +import com.oracle.java.testlibrary.*; + +public class BooleanFlagWithInvalidValue { + public static void main(String[] args) throws Exception { + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( + "-XX:+UseLargePages=8", "-version"); + + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldContain("Improperly specified VM option 'UseLargePages=8'"); + output.shouldHaveExitValue(1); + + pb = ProcessTools.createJavaProcessBuilder( + "-XX:-UseLargePages=8", "-version"); + + output = new OutputAnalyzer(pb.start()); + output.shouldContain("Improperly specified VM option 'UseLargePages=8'"); + output.shouldHaveExitValue(1); + } +} diff -r a413bcd552a4 -r 5fc51c1ecdeb test/runtime/CommandLine/FlagWithInvalidValue.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/runtime/CommandLine/FlagWithInvalidValue.java Tue Mar 05 23:44:54 2013 +0100 @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8006298 + * @summary Setting a flag to an invalid value should print a useful error message + * @library /testlibrary + */ + +import com.oracle.java.testlibrary.*; + +public class FlagWithInvalidValue { + public static void main(String[] args) throws Exception { + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( + "-XX:ObjectAlignmentInBytes=v", "-version"); + + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldContain("Improperly specified VM option 'ObjectAlignmentInBytes=v'"); + output.shouldHaveExitValue(1); + } +} diff -r a413bcd552a4 -r 5fc51c1ecdeb test/runtime/CommandLine/NonBooleanFlagWithInvalidBooleanPrefix.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/runtime/CommandLine/NonBooleanFlagWithInvalidBooleanPrefix.java Tue Mar 05 23:44:54 2013 +0100 @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8006298 + * @summary Using a bool (+/-) prefix on non-bool flag should result in a useful error message + * @library /testlibrary + */ + +import com.oracle.java.testlibrary.*; + +public class NonBooleanFlagWithInvalidBooleanPrefix { + public static void main(String[] args) throws Exception { + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( + "-XX:-ObjectAlignmentInBytes=16", "-version"); + + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldContain("Unexpected +/- setting in VM option 'ObjectAlignmentInBytes=16'"); + output.shouldHaveExitValue(1); + + pb = ProcessTools.createJavaProcessBuilder( + "-XX:+ObjectAlignmentInBytes=16", "-version"); + + output = new OutputAnalyzer(pb.start()); + output.shouldContain("Unexpected +/- setting in VM option 'ObjectAlignmentInBytes=16'"); + output.shouldHaveExitValue(1); + + } +} diff -r a413bcd552a4 -r 5fc51c1ecdeb test/runtime/CommandLine/UnrecognizedVMOption.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/runtime/CommandLine/UnrecognizedVMOption.java Tue Mar 05 23:44:54 2013 +0100 @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8006298 + * @summary Using an unrecognized VM option should print the name of the option + * @library /testlibrary + */ + +import com.oracle.java.testlibrary.*; + +public class UnrecognizedVMOption { + public static void main(String[] args) throws Exception { + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( + "-XX:bogus_option", "-version"); + + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldContain("Unrecognized VM option 'bogus_option'"); + output.shouldHaveExitValue(1); + } +} diff -r a413bcd552a4 -r 5fc51c1ecdeb test/runtime/NMT/AllocTestType.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/runtime/NMT/AllocTestType.java Tue Mar 05 23:44:54 2013 +0100 @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @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 + * @build AllocTestType + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:NativeMemoryTracking=detail AllocTestType + */ + +import com.oracle.java.testlibrary.*; +import sun.hotspot.WhiteBox; + +public class AllocTestType { + + public static void main(String args[]) throws Exception { + OutputAnalyzer output; + + // Grab my own PID + String pid = Integer.toString(ProcessTools.getProcessId()); + ProcessBuilder pb = new ProcessBuilder(); + + // Use WB API to alloc with the mtTest type + if (!WhiteBox.getWhiteBox().NMTAllocTest()) { + throw new Exception("Call to WB API NMTAllocTest() failed"); + } + + // Use WB API to ensure that all data has been merged before we continue + if (!WhiteBox.getWhiteBox().NMTWaitForDataMerge()) { + throw new Exception("Call to WB API NMTWaitForDataMerge() failed"); + } + + // Run 'jcmd VM.native_memory summary' + pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "summary"}); + output = new OutputAnalyzer(pb.start()); + output.shouldContain("Test (reserved=512KB, committed=512KB)"); + + // Free the memory allocated by NMTAllocTest + if (!WhiteBox.getWhiteBox().NMTFreeTestMemory()) { + throw new Exception("Call to WB API NMTFreeTestMemory() failed"); + } + + // Use WB API to ensure that all data has been merged before we continue + if (!WhiteBox.getWhiteBox().NMTWaitForDataMerge()) { + throw new Exception("Call to WB API NMTWaitForDataMerge() failed"); + } + output = new OutputAnalyzer(pb.start()); + output.shouldNotContain("Test (reserved="); + } +} diff -r a413bcd552a4 -r 5fc51c1ecdeb test/runtime/NMT/BaselineWithParameter.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/runtime/NMT/BaselineWithParameter.java Tue Mar 05 23:44:54 2013 +0100 @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8004802 + * @key nmt jcmd regression + * @summary Regression test for invoking a jcmd with baseline=false, result was that the target VM crashed + * @library /testlibrary + * @run main/othervm -XX:NativeMemoryTracking=detail BaselineWithParameter + */ + +import com.oracle.java.testlibrary.*; + +public class BaselineWithParameter { + + public static void main(String args[]) throws Exception { + // Grab my own PID + String pid = Integer.toString(ProcessTools.getProcessId()); + OutputAnalyzer output; + + ProcessBuilder pb = new ProcessBuilder(); + + // Run 'jcmd VM.native_memory baseline=false' + pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "baseline=false"}); + pb.start(); + + // Run 'jcmd VM.native_memory summary=false' + pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "summary=false"}); + output = new OutputAnalyzer(pb.start()); + output.shouldContain("No command to execute"); + + } +} diff -r a413bcd552a4 -r 5fc51c1ecdeb test/runtime/NMT/CommandLineDetail.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/runtime/NMT/CommandLineDetail.java Tue Mar 05 23:44:54 2013 +0100 @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + /* + * @test + * @key nmt + * @summary Running with NMT detail should not result in an error or warning + * @library /testlibrary + */ + +import com.oracle.java.testlibrary.*; + +public class CommandLineDetail { + + public static void main(String args[]) throws Exception { + + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( + "-XX:NativeMemoryTracking=detail", + "-version"); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldNotContain("error"); + output.shouldNotContain("warning"); + output.shouldHaveExitValue(0); + } +} diff -r a413bcd552a4 -r 5fc51c1ecdeb test/runtime/NMT/CommandLineEmptyArgument.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/runtime/NMT/CommandLineEmptyArgument.java Tue Mar 05 23:44:54 2013 +0100 @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + /* + * @test + * @key nmt + * @summary Empty argument to NMT should result in an informative error message + * @library /testlibrary + */ + +import com.oracle.java.testlibrary.*; + +public class CommandLineEmptyArgument { + + public static void main(String args[]) throws Exception { + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-XX:NativeMemoryTracking="); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldContain("Syntax error, expecting -XX:NativeMemoryTracking=[off|summary|detail]"); + output.shouldHaveExitValue(1); + } +} diff -r a413bcd552a4 -r 5fc51c1ecdeb test/runtime/NMT/CommandLineInvalidArgument.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/runtime/NMT/CommandLineInvalidArgument.java Tue Mar 05 23:44:54 2013 +0100 @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + /* + * @test + * @key nmt + * @summary Invalid argument to NMT should result in an informative error message + * @library /testlibrary + */ + +import com.oracle.java.testlibrary.*; + +public class CommandLineInvalidArgument { + + public static void main(String args[]) throws Exception { + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-XX:NativeMemoryTracking=apa"); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldContain("Syntax error, expecting -XX:NativeMemoryTracking=[off|summary|detail]"); + output.shouldHaveExitValue(1); + } +} diff -r a413bcd552a4 -r 5fc51c1ecdeb test/runtime/NMT/CommandLineSummary.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/runtime/NMT/CommandLineSummary.java Tue Mar 05 23:44:54 2013 +0100 @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + /* + * @test + * @key nmt + * @summary Running with NMT summary should not result in an error or warning + * @library /testlibrary + */ + +import com.oracle.java.testlibrary.*; + +public class CommandLineSummary { + + public static void main(String args[]) throws Exception { + + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( + "-XX:NativeMemoryTracking=summary", + "-version"); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldNotContain("error"); + output.shouldNotContain("warning"); + output.shouldHaveExitValue(0); + } +} diff -r a413bcd552a4 -r 5fc51c1ecdeb test/runtime/NMT/CommandLineTurnOffNMT.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/runtime/NMT/CommandLineTurnOffNMT.java Tue Mar 05 23:44:54 2013 +0100 @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + /* + * @test + * @key nmt + * @summary Turning off NMT should not result in an error or warning + * @library /testlibrary + */ + +import com.oracle.java.testlibrary.*; + +public class CommandLineTurnOffNMT { + + public static void main(String args[]) throws Exception { + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( + "-XX:NativeMemoryTracking=off", + "-version"); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldNotContain("error"); + output.shouldNotContain("warning"); + output.shouldHaveExitValue(0); + } +} diff -r a413bcd552a4 -r 5fc51c1ecdeb test/runtime/NMT/JcmdScale.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/runtime/NMT/JcmdScale.java Tue Mar 05 23:44:54 2013 +0100 @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @key nmt jcmd + * @summary Test the NMT scale parameter + * @library /testlibrary + * @run main/othervm -XX:NativeMemoryTracking=summary JcmdScale + */ + +import com.oracle.java.testlibrary.*; + +public class JcmdScale { + + public static void main(String args[]) throws Exception { + ProcessBuilder pb = new ProcessBuilder(); + OutputAnalyzer output; + // Grab my own PID + String pid = Integer.toString(ProcessTools.getProcessId()); + + pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "scale=KB"}); + output = new OutputAnalyzer(pb.start()); + output.shouldContain("KB, committed="); + + pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "scale=MB"}); + output = new OutputAnalyzer(pb.start()); + output.shouldContain("MB, committed="); + + pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "scale=GB"}); + output = new OutputAnalyzer(pb.start()); + output.shouldContain("GB, committed="); + + pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "scale=apa"}); + output = new OutputAnalyzer(pb.start()); + output.shouldContain("Incorrect scale value: apa"); + + pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "summary", "scale=GB"}); + output = new OutputAnalyzer(pb.start()); + output.shouldContain("GB, committed="); + + pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "summary", "scale=apa"}); + output = new OutputAnalyzer(pb.start()); + output.shouldContain("Incorrect scale value: apa"); + + } +} diff -r a413bcd552a4 -r 5fc51c1ecdeb test/runtime/NMT/JcmdWithNMTDisabled.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/runtime/NMT/JcmdWithNMTDisabled.java Tue Mar 05 23:44:54 2013 +0100 @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @key nmt jcmd + * @summary Verify that jcmd correctly reports that NMT is not enabled + * @library /testlibrary + * First run without enabling NMT + * @run main/othervm JcmdWithNMTDisabled + * Then run with explicitly disabling NMT, should not be any difference + * @run main/othervm -XX:NativeMemoryTracking=off JcmdWithNMTDisabled + */ + +import com.oracle.java.testlibrary.*; + +public class JcmdWithNMTDisabled { + static ProcessBuilder pb = new ProcessBuilder(); + static String pid; + + public static void main(String args[]) throws Exception { + // Grab my own PID + pid = Integer.toString(ProcessTools.getProcessId()); + + jcmdCommand("summary"); + jcmdCommand("detail"); + jcmdCommand("baseline"); + jcmdCommand("summary.diff"); + jcmdCommand("detail.diff"); + jcmdCommand("scale=GB"); + jcmdCommand("shutdown"); + } + + // Helper method for invoking different jcmd calls, all should fail with the same message saying NMT is not enabled + public static void jcmdCommand(String command) throws Exception { + + pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", command}); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + + // Verify that jcmd reports that NMT is not enabled + output.shouldContain("Native memory tracking is not enabled"); + } +} diff -r a413bcd552a4 -r 5fc51c1ecdeb test/runtime/NMT/PrintNMTStatistics.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/runtime/NMT/PrintNMTStatistics.java Tue Mar 05 23:44:54 2013 +0100 @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @key nmt regression + * @bug 8005936 + * @summary Make sure PrintNMTStatistics works on normal JVM exit + * @library /testlibrary /testlibrary/whitebox + * @run compile PrintNMTStatistics.java + */ + +import com.oracle.java.testlibrary.*; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import sun.hotspot.WhiteBox; + +public class PrintNMTStatistics { + + public static void main(String args[]) throws Exception { + + // We start a new java process running with an argument and use WB API to ensure + // we have data for NMT on VM exit + if (args.length > 0) { + // Use WB API to ensure that all data has been merged before we continue + if (!WhiteBox.getWhiteBox().NMTWaitForDataMerge()) { + throw new Exception("Call to WB API NMTWaitForDataMerge() failed"); + } + return; + } + + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( + "-XX:+UnlockDiagnosticVMOptions", + "-XX:NativeMemoryTracking=summary", + "+XX:+PrintNMTStatistics", + "PrintNMTStatistics", + "test"); + + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldContain("Java Heap (reserved="); + output.shouldNotContain("error"); + output.shouldNotContain("warning"); + output.shouldHaveExitValue(0); + } +} diff -r a413bcd552a4 -r 5fc51c1ecdeb test/runtime/NMT/PrintNMTStatisticsWithNMTDisabled.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/runtime/NMT/PrintNMTStatisticsWithNMTDisabled.java Tue Mar 05 23:44:54 2013 +0100 @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + /* + * @test + * @key nmt + * @summary Trying to enable PrintNMTStatistics should result in a warning + * @library /testlibrary + */ + +import com.oracle.java.testlibrary.*; + +public class PrintNMTStatisticsWithNMTDisabled { + + public static void main(String args[]) throws Exception { + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( + "-XX:+UnlockDiagnosticVMOptions", + "-XX:+PrintNMTStatistics", + "-version"); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldContain("warning: PrintNMTStatistics is disabled, because native memory tracking is not enabled"); + output.shouldHaveExitValue(0); + } +} diff -r a413bcd552a4 -r 5fc51c1ecdeb test/runtime/NMT/ShutdownTwice.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/runtime/NMT/ShutdownTwice.java Tue Mar 05 23:44:54 2013 +0100 @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @key nmt jcmd + * @summary Run shutdown twice + * @library /testlibrary + * @run main/othervm -XX:NativeMemoryTracking=detail ShutdownTwice + */ + +import com.oracle.java.testlibrary.*; + +public class ShutdownTwice { + + public static void main(String args[]) throws Exception { + // Grab my own PID + String pid = Integer.toString(ProcessTools.getProcessId()); + OutputAnalyzer output; + + ProcessBuilder pb = new ProcessBuilder(); + + // Run 'jcmd VM.native_memory shutdown' + pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "shutdown"}); + output = new OutputAnalyzer(pb.start()); + + // Verify that jcmd reports that NMT is shutting down + output.shouldContain("Shutdown is in progress, it will take a few moments to completely shutdown"); + + // Run shutdown again + output = new OutputAnalyzer(pb.start()); + + // Verify that jcmd reports that NMT has been shutdown already + output.shouldContain("Native memory tracking has been shutdown by user"); + } +} diff -r a413bcd552a4 -r 5fc51c1ecdeb test/runtime/NMT/SummaryAfterShutdown.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/runtime/NMT/SummaryAfterShutdown.java Tue Mar 05 23:44:54 2013 +0100 @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @key nmt jcmd + * @summary Verify that jcmd correctly reports that NMT is not enabled after a shutdown + * @library /testlibrary + * @run main/othervm -XX:NativeMemoryTracking=detail SummaryAfterShutdown + */ + +import com.oracle.java.testlibrary.*; + +public class SummaryAfterShutdown { + + public static void main(String args[]) throws Exception { + OutputAnalyzer output; + // Grab my own PID + String pid = Integer.toString(ProcessTools.getProcessId()); + ProcessBuilder pb = new ProcessBuilder(); + + // Run 'jcmd VM.native_memory shutdown' + pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "shutdown"}); + output = new OutputAnalyzer(pb.start()); + + // Verify that jcmd reports that NMT is shutting down + output.shouldContain("Shutdown is in progress, it will take a few moments to completely shutdown"); + + // Run 'jcmd VM.native_memory summary' + pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "summary"}); + output = new OutputAnalyzer(pb.start()); + + // Verify that jcmd reports that NMT has been shutdown + output.shouldContain("Native memory tracking has been shutdown by user"); + } +} diff -r a413bcd552a4 -r 5fc51c1ecdeb test/runtime/NMT/SummarySanityCheck.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/runtime/NMT/SummarySanityCheck.java Tue Mar 05 23:44:54 2013 +0100 @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @key nmt jcmd + * @summary Sanity check the output of NMT + * @library /testlibrary /testlibrary/whitebox + * @build SummarySanityCheck + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:NativeMemoryTracking=summary -XX:+WhiteBoxAPI SummarySanityCheck + */ + +import com.oracle.java.testlibrary.*; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import sun.hotspot.WhiteBox; + +public class SummarySanityCheck { + + private static String jcmdout; + public static void main(String args[]) throws Exception { + // Grab my own PID + String pid = Integer.toString(ProcessTools.getProcessId()); + + // Use WB API to ensure that all data has been merged before we continue + if (!WhiteBox.getWhiteBox().NMTWaitForDataMerge()) { + throw new Exception("Call to WB API NMTWaitForDataMerge() failed"); + } + + ProcessBuilder pb = new ProcessBuilder(); + + // Run 'jcmd VM.native_memory summary scale=KB' + pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "summary", "scale=KB"}); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + + jcmdout = output.getOutput(); + // Split by '-' to get the 'groups' + String[] lines = jcmdout.split("\n"); + + if (lines.length == 0) { + throwTestException("Failed to parse jcmd output"); + } + + int totalCommitted = 0, totalReserved = 0; + int totalCommittedSum = 0, totalReservedSum = 0; + + // Match '- (reserved=KB, committed=KB) + Pattern mtTypePattern = Pattern.compile("-\\s+(?[\\w\\s]+)\\(reserved=(?\\d+)KB,\\scommitted=(?\\d+)KB\\)"); + // Match 'Total: reserved=KB, committed=KB' + Pattern totalMemoryPattern = Pattern.compile("Total\\:\\s\\sreserved=(?\\d+)KB,\\s\\scommitted=(?\\d+)KB"); + + for (int i = 0; i < lines.length; i++) { + if (lines[i].startsWith("Total")) { + Matcher totalMemoryMatcher = totalMemoryPattern.matcher(lines[i]); + + if (totalMemoryMatcher.matches() && totalMemoryMatcher.groupCount() == 2) { + totalCommitted = Integer.parseInt(totalMemoryMatcher.group("committed")); + totalReserved = Integer.parseInt(totalMemoryMatcher.group("reserved")); + } else { + throwTestException("Failed to match the expected groups in 'Total' memory part"); + } + } else if (lines[i].startsWith("-")) { + Matcher typeMatcher = mtTypePattern.matcher(lines[i]); + if (typeMatcher.matches()) { + int typeCommitted = Integer.parseInt(typeMatcher.group("committed")); + int typeReserved = Integer.parseInt(typeMatcher.group("reserved")); + + // Make sure reserved is always less or equals + if (typeCommitted > typeReserved) { + throwTestException("Committed (" + typeCommitted + ") was more than Reserved (" + + typeReserved + ") for mtType: " + typeMatcher.group("typename")); + } + + // Add to total and compare them in the end + totalCommittedSum += typeCommitted; + totalReservedSum += typeReserved; + } else { + throwTestException("Failed to match the group on line " + i); + } + } + } + + // See if they add up correctly, rounding is a problem so make sure we're within +/- 8KB + int committedDiff = totalCommitted - totalCommittedSum; + if (committedDiff > 8 || committedDiff < -8) { + throwTestException("Total committed (" + totalCommitted + ") did not match the summarized committed (" + totalCommittedSum + ")" ); + } + + int reservedDiff = totalReserved - totalReservedSum; + if (reservedDiff > 8 || reservedDiff < -8) { + throwTestException("Total reserved (" + totalReserved + ") did not match the summarized reserved (" + totalReservedSum + ")" ); + } + } + + private static void throwTestException(String reason) throws Exception { + throw new Exception(reason + " . Stdout is :\n" + jcmdout); + } +} diff -r a413bcd552a4 -r 5fc51c1ecdeb test/sanity/WBApi.java --- a/test/sanity/WBApi.java Tue Mar 05 21:58:51 2013 +0100 +++ b/test/sanity/WBApi.java Tue Mar 05 23:44:54 2013 +0100 @@ -1,8 +1,33 @@ +/* + * Copyright (c) 2012, 2013 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + /* * @test WBApi * @summary verify that whitebox functions can be linked and executed - * @run compile -J-XX:+UnlockDiagnosticVMOptions -J-XX:+WhiteBoxAPI WBApi.java - * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI WBApi + * @library /testlibrary /testlibrary/whitebox + * @build WBApi + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI WBApi */ import sun.hotspot.WhiteBox; diff -r a413bcd552a4 -r 5fc51c1ecdeb test/serviceability/ParserTest.java --- a/test/serviceability/ParserTest.java Tue Mar 05 21:58:51 2013 +0100 +++ b/test/serviceability/ParserTest.java Tue Mar 05 23:44:54 2013 +0100 @@ -1,8 +1,33 @@ +/* + * Copyright (c) 2012, 2013 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + /* * @test ParserTest - * @summary verify that whitebox functions can be linked and executed - * @run compile -J-XX:+UnlockDiagnosticVMOptions -J-XX:+WhiteBoxAPI ParserTest.java - * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI ParserTest + * @summary Test that the diagnostic command arguemnt parser works + * @library /testlibrary /testlibrary/whitebox + * @build ParserTest + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI ParserTest */ import java.math.BigInteger; diff -r a413bcd552a4 -r 5fc51c1ecdeb test/testlibrary/ClassFileInstaller.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/testlibrary/ClassFileInstaller.java Tue Mar 05 23:44:54 2013 +0100 @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.InputStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.StandardCopyOption; + +/** + * Dump a class file for a class on the class path in the current directory + */ +public class ClassFileInstaller { + /** + * @param args The names of the classes to dump + * @throws Exception + */ + public static void main(String... args) throws Exception { + for (String arg : args) { + ClassLoader cl = ClassFileInstaller.class.getClassLoader(); + + // Convert dotted class name to a path to a class file + String pathName = arg.replace('.', '/').concat(".class"); + InputStream is = cl.getResourceAsStream(pathName); + + // Create the class file's package directory + Path p = Paths.get(pathName); + Files.createDirectories(p.getParent()); + // Create the class file + Files.copy(is, p, StandardCopyOption.REPLACE_EXISTING); + } + } +} diff -r a413bcd552a4 -r 5fc51c1ecdeb test/testlibrary/OutputAnalyzerTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/testlibrary/OutputAnalyzerTest.java Tue Mar 05 23:44:54 2013 +0100 @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @summary Test the OutputAnalyzer utility class + * @library /testlibrary + */ + +import com.oracle.java.testlibrary.OutputAnalyzer; + +public class OutputAnalyzerTest { + + public static void main(String args[]) throws Exception { + + String stdout = "aaaaaa"; + String stderr = "bbbbbb"; + + OutputAnalyzer output = new OutputAnalyzer(stdout, stderr); + + if (!stdout.equals(output.getStdout())) { + throw new Exception("getStdout() returned '" + output.getStdout() + "', expected '" + stdout + "'"); + } + + if (!stderr.equals(output.getStderr())) { + throw new Exception("getStderr() returned '" + output.getStderr() + "', expected '" + stderr + "'"); + } + + try { + output.shouldContain(stdout); + output.stdoutShouldContain(stdout); + output.shouldContain(stderr); + output.stderrShouldContain(stderr); + } catch (RuntimeException e) { + throw new Exception("shouldContain() failed", e); + } + + try { + output.shouldContain("cccc"); + throw new Exception("shouldContain() failed to throw exception"); + } catch (RuntimeException e) { + // expected + } + + try { + output.stdoutShouldContain(stderr); + throw new Exception("stdoutShouldContain() failed to throw exception"); + } catch (RuntimeException e) { + // expected + } + + try { + output.stderrShouldContain(stdout); + throw new Exception("stdoutShouldContain() failed to throw exception"); + } catch (RuntimeException e) { + // expected + } + + try { + output.shouldNotContain("cccc"); + output.stdoutShouldNotContain("cccc"); + output.stderrShouldNotContain("cccc"); + } catch (RuntimeException e) { + throw new Exception("shouldNotContain() failed", e); + } + + try { + output.shouldNotContain(stdout); + throw new Exception("shouldContain() failed to throw exception"); + } catch (RuntimeException e) { + // expected + } + + try { + output.stdoutShouldNotContain(stdout); + throw new Exception("shouldContain() failed to throw exception"); + } catch (RuntimeException e) { + // expected + } + + try { + output.stderrShouldNotContain(stderr); + throw new Exception("shouldContain() failed to throw exception"); + } catch (RuntimeException e) { + // expected + } + } +} diff -r a413bcd552a4 -r 5fc51c1ecdeb test/testlibrary/com/oracle/java/testlibrary/JDKToolFinder.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/testlibrary/com/oracle/java/testlibrary/JDKToolFinder.java Tue Mar 05 23:44:54 2013 +0100 @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.oracle.java.testlibrary; + +import java.io.File; + +public final class JDKToolFinder { + + private JDKToolFinder() { + } + + /** + * Returns the full path to an executable in jdk/bin based on System property + * test.jdk (set by jtreg test suite) + * + * @return Full path to an executable in jdk/bin + */ + public static String getJDKTool(String tool) { + String binPath = System.getProperty("test.jdk"); + if (binPath == null) { + throw new RuntimeException("System property 'test.jdk' not set. This property is normally set by jtreg. " + + "When running test separately, set this property using '-Dtest.jdk=/path/to/jdk'."); + } + + binPath += File.separatorChar + "bin" + File.separatorChar + tool; + + return binPath; + } +} diff -r a413bcd552a4 -r 5fc51c1ecdeb test/testlibrary/com/oracle/java/testlibrary/OutputAnalyzer.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/testlibrary/com/oracle/java/testlibrary/OutputAnalyzer.java Tue Mar 05 23:44:54 2013 +0100 @@ -0,0 +1,191 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.oracle.java.testlibrary; + +import java.io.IOException; + +public final class OutputAnalyzer { + + private final String stdout; + private final String stderr; + private final int exitValue; + + /** + * Create an OutputAnalyzer, a utility class for verifying output and exit + * value from a Process + * + * @param process Process to analyze + * @throws IOException If an I/O error occurs. + */ + public OutputAnalyzer(Process process) throws IOException { + OutputBuffer output = ProcessTools.getOutput(process); + exitValue = process.exitValue(); + this.stdout = output.getStdout(); + this.stderr = output.getStderr(); + } + + /** + * Create an OutputAnalyzer, a utility class for verifying output + * + * @param buf String buffer to analyze + */ + public OutputAnalyzer(String buf) { + this(buf, buf); + } + + /** + * Create an OutputAnalyzer, a utility class for verifying output + * + * @param stdout stdout buffer to analyze + * @param stderr stderr buffer to analyze + */ + public OutputAnalyzer(String stdout, String stderr) { + this.stdout = stdout; + this.stderr = stderr; + exitValue = -1; + } + + /** + * Verify that the stdout and stderr contents of output buffer contains the string + * + * @param expectedString String that buffer should contain + * @throws RuntimeException If the string was not found + */ + public void shouldContain(String expectedString) { + if (!stdout.contains(expectedString) && !stderr.contains(expectedString)) { + throw new RuntimeException("'" + expectedString + "' missing from stdout/stderr: [" + stdout + stderr + "]\n"); + } + } + + /** + * Verify that the stdout contents of output buffer contains the string + * + * @param expectedString String that buffer should contain + * @throws RuntimeException If the string was not found + */ + public void stdoutShouldContain(String expectedString) { + if (!stdout.contains(expectedString)) { + throw new RuntimeException("'" + expectedString + "' missing from stdout: [" + stdout + "]\n"); + } + } + + /** + * Verify that the stderr contents of output buffer contains the string + * + * @param expectedString String that buffer should contain + * @throws RuntimeException If the string was not found + */ + public void stderrShouldContain(String expectedString) { + if (!stderr.contains(expectedString)) { + throw new RuntimeException("'" + expectedString + "' missing from stderr: [" + stderr + "]\n"); + } + } + + /** + * Verify that the stdout and stderr contents of output buffer does not contain the string + * + * @param expectedString String that the buffer should not contain + * @throws RuntimeException If the string was found + */ + public void shouldNotContain(String notExpectedString) { + if (stdout.contains(notExpectedString)) { + throw new RuntimeException("'" + notExpectedString + "' found in stdout: [" + stdout + "]\n"); + } + if (stderr.contains(notExpectedString)) { + throw new RuntimeException("'" + notExpectedString + "' found in stderr: [" + stderr + "]\n"); + } + } + + /** + * Verify that the stdout contents of output buffer does not contain the string + * + * @param expectedString String that the buffer should not contain + * @throws RuntimeException If the string was found + */ + public void stdoutShouldNotContain(String notExpectedString) { + if (stdout.contains(notExpectedString)) { + throw new RuntimeException("'" + notExpectedString + "' found in stdout: [" + stdout + "]\n"); + } + } + + /** + * Verify that the stderr contents of output buffer does not contain the string + * + * @param expectedString String that the buffer should not contain + * @throws RuntimeException If the string was found + */ + public void stderrShouldNotContain(String notExpectedString) { + if (stderr.contains(notExpectedString)) { + throw new RuntimeException("'" + notExpectedString + "' found in stderr: [" + stderr + "]\n"); + } + } + + /** + * Verifiy the exit value of the process + * + * @param expectedExitValue Expected exit value from process + * @throws RuntimeException If the exit value from the process did not match the expected value + */ + public void shouldHaveExitValue(int expectedExitValue) { + if (getExitValue() != expectedExitValue) { + throw new RuntimeException("Exit value " + getExitValue() + " , expected to get " + expectedExitValue); + } + } + + /** + * Get the contents of the output buffer (stdout and stderr) + * + * @return Content of the output buffer + */ + public String getOutput() { + return stdout + stderr; + } + + /** + * Get the contents of the stdout buffer + * + * @return Content of the stdout buffer + */ + public String getStdout() { + return stdout; + } + + /** + * Get the contents of the stderr buffer + * + * @return Content of the stderr buffer + */ + public String getStderr() { + return stderr; + } + + /** + * Get the process exit value + * + * @return Process exit value + */ + public int getExitValue() { + return exitValue; + } +} diff -r a413bcd552a4 -r 5fc51c1ecdeb test/testlibrary/com/oracle/java/testlibrary/OutputBuffer.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/testlibrary/com/oracle/java/testlibrary/OutputBuffer.java Tue Mar 05 23:44:54 2013 +0100 @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.oracle.java.testlibrary; + +public class OutputBuffer { + private final String stdout; + private final String stderr; + + /** + * Create an OutputBuffer, a class for storing and managing stdout and stderr + * results separately + * + * @param stdout stdout result + * @param stderr stderr result + */ + public OutputBuffer(String stdout, String stderr) { + this.stdout = stdout; + this.stderr = stderr; + } + + /** + * Returns the stdout result + * + * @return stdout result + */ + public String getStdout() { + return stdout; + } + + /** + * Returns the stderr result + * + * @return stderr result + */ + public String getStderr() { + return stderr; + } +} diff -r a413bcd552a4 -r 5fc51c1ecdeb test/testlibrary/com/oracle/java/testlibrary/ProcessTools.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/testlibrary/com/oracle/java/testlibrary/ProcessTools.java Tue Mar 05 23:44:54 2013 +0100 @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.oracle.java.testlibrary; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.lang.management.ManagementFactory; +import java.lang.management.RuntimeMXBean; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Collections; + +import sun.management.VMManagement; + +public final class ProcessTools { + + private ProcessTools() { + } + + /** + * Pumps stdout and stderr from running the process into a String. + * + * @param processHandler ProcessHandler to run. + * @return Output from process. + * @throws IOException If an I/O error occurs. + */ + public static OutputBuffer getOutput(ProcessBuilder processBuilder) throws IOException { + return getOutput(processBuilder.start()); + } + + /** + * Pumps stdout and stderr the running process into a String. + * + * @param process Process to pump. + * @return Output from process. + * @throws IOException If an I/O error occurs. + */ + public static OutputBuffer getOutput(Process process) throws IOException { + ByteArrayOutputStream stderrBuffer = new ByteArrayOutputStream(); + ByteArrayOutputStream stdoutBuffer = new ByteArrayOutputStream(); + StreamPumper outPumper = new StreamPumper(process.getInputStream(), stdoutBuffer); + StreamPumper errPumper = new StreamPumper(process.getErrorStream(), stderrBuffer); + Thread outPumperThread = new Thread(outPumper); + Thread errPumperThread = new Thread(errPumper); + + outPumperThread.setDaemon(true); + errPumperThread.setDaemon(true); + + outPumperThread.start(); + errPumperThread.start(); + + try { + process.waitFor(); + outPumperThread.join(); + errPumperThread.join(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + return null; + } + + return new OutputBuffer(stdoutBuffer.toString(), stderrBuffer.toString()); + } + + /** + * Get the process id of the current running Java process + * + * @return Process id + */ + public static int getProcessId() throws Exception { + + // Get the current process id using a reflection hack + RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean(); + Field jvm = runtime.getClass().getDeclaredField("jvm"); + + jvm.setAccessible(true); + VMManagement mgmt = (sun.management.VMManagement) jvm.get(runtime); + + Method pid_method = mgmt.getClass().getDeclaredMethod("getProcessId"); + + pid_method.setAccessible(true); + + int pid = (Integer) pid_method.invoke(mgmt); + + return pid; + } + + /** + * Get platform specific VM arguments (e.g. -d64 on 64bit Solaris) + * + * @return String[] with platform specific arguments, empty if there are none + */ + public static String[] getPlatformSpecificVMArgs() { + String osName = System.getProperty("os.name"); + String dataModel = System.getProperty("sun.arch.data.model"); + + if (osName.equals("SunOS") && dataModel.equals("64")) { + return new String[] { "-d64" }; + } + + return new String[] {}; + } + + /** + * Create ProcessBuilder using the java launcher from the jdk to be tested and + * with any platform specific arguments prepended + */ + public static ProcessBuilder createJavaProcessBuilder(String... command) throws Exception { + String javapath = JDKToolFinder.getJDKTool("java"); + + ArrayList args = new ArrayList<>(); + args.add(javapath); + Collections.addAll(args, getPlatformSpecificVMArgs()); + Collections.addAll(args, command); + + return new ProcessBuilder(args.toArray(new String[args.size()])); + + } + +} diff -r a413bcd552a4 -r 5fc51c1ecdeb test/testlibrary/com/oracle/java/testlibrary/StreamPumper.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/testlibrary/com/oracle/java/testlibrary/StreamPumper.java Tue Mar 05 23:44:54 2013 +0100 @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.oracle.java.testlibrary; + +import java.io.OutputStream; +import java.io.InputStream; +import java.io.IOException; + +public final class StreamPumper implements Runnable { + + private static final int BUF_SIZE = 256; + + private final OutputStream out; + private final InputStream in; + + /** + * Create a StreamPumper that reads from in and writes to out. + * + * @param in The stream to read from. + * @param out The stream to write to. + */ + public StreamPumper(InputStream in, OutputStream out) { + this.in = in; + this.out = out; + } + + /** + * Implements Thread.run(). Continuously read from in and write + * to out until in has reached end of stream. Abort + * on interruption. Abort on IOExceptions. + */ + @Override + public void run() { + int length; + InputStream localIn = in; + OutputStream localOut = out; + byte[] buffer = new byte[BUF_SIZE]; + + try { + while (!Thread.interrupted() && (length = localIn.read(buffer)) > 0) { + localOut.write(buffer, 0, length); + } + } catch (IOException e) { + // Just abort if something like this happens. + e.printStackTrace(); + } finally { + try { + localOut.flush(); + in.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } +} diff -r a413bcd552a4 -r 5fc51c1ecdeb test/testlibrary/whitebox/sun/hotspot/WhiteBox.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/testlibrary/whitebox/sun/hotspot/WhiteBox.java Tue Mar 05 23:44:54 2013 +0100 @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2012, 2013 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package sun.hotspot; + +import java.lang.reflect.Method; +import java.security.BasicPermission; +import sun.hotspot.parser.DiagnosticCommand; + +public class WhiteBox { + + @SuppressWarnings("serial") + public static class WhiteBoxPermission extends BasicPermission { + public WhiteBoxPermission(String s) { + super(s); + } + } + + private WhiteBox() {} + private static final WhiteBox instance = new WhiteBox(); + private static native void registerNatives(); + + /** + * Returns the singleton WhiteBox instance. + * + * The returned WhiteBox object should be carefully guarded + * by the caller, since it can be used to read and write data + * at arbitrary memory addresses. It must never be passed to + * untrusted code. + */ + public synchronized static WhiteBox getWhiteBox() { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + sm.checkPermission(new WhiteBoxPermission("getInstance")); + } + return instance; + } + + static { + registerNatives(); + } + + // Memory + public native long getObjectAddress(Object o); + public native int getHeapOopSize(); + + // Runtime + // Make sure class name is in the correct format + public boolean isClassAlive(String name) { + return isClassAlive0(name.replace('.', '/')); + } + private native boolean isClassAlive0(String name); + + // G1 + public native boolean g1InConcurrentMark(); + public native boolean g1IsHumongous(Object o); + public native long g1NumFreeRegions(); + public native int g1RegionSize(); + public native Object[] parseCommandLine(String commandline, DiagnosticCommand[] args); + + // NMT + public native boolean NMTAllocTest(); + public native boolean NMTFreeTestMemory(); + public native boolean NMTWaitForDataMerge(); + + // Compiler + public native void deoptimizeAll(); + public native boolean isMethodCompiled(Method method); + public native boolean isMethodCompilable(Method method); + public native boolean isMethodQueuedForCompilation(Method method); + public native int deoptimizeMethod(Method method); + public native void makeMethodNotCompilable(Method method); + public native int getMethodCompilationLevel(Method method); + public native boolean setDontInlineMethod(Method method, boolean value); + public native int getCompileQueuesSize(); +} diff -r a413bcd552a4 -r 5fc51c1ecdeb test/testlibrary/whitebox/sun/hotspot/parser/DiagnosticCommand.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/testlibrary/whitebox/sun/hotspot/parser/DiagnosticCommand.java Tue Mar 05 23:44:54 2013 +0100 @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2012, 2013 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package sun.hotspot.parser; + +public class DiagnosticCommand { + + public enum DiagnosticArgumentType { + JLONG, BOOLEAN, STRING, NANOTIME, STRINGARRAY, MEMORYSIZE + } + + private String name; + private String desc; + private DiagnosticArgumentType type; + private boolean mandatory; + private String defaultValue; + + public DiagnosticCommand(String name, String desc, DiagnosticArgumentType type, + boolean mandatory, String defaultValue) { + this.name = name; + this.desc = desc; + this.type = type; + this.mandatory = mandatory; + this.defaultValue = defaultValue; + } + + public String getName() { + return name; + } + + public String getDesc() { + return desc; + } + + public DiagnosticArgumentType getType() { + return type; + } + + public boolean isMandatory() { + return mandatory; + } + + public String getDefaultValue() { + return defaultValue; + } +}