Mercurial > hg > graal-jvmci-8
changeset 8250:edc414f52e2b
Merge.
author | Christian Humer <christian.humer@gmail.com> |
---|---|
date | Tue, 12 Mar 2013 11:38:52 +0100 |
parents | aad7e9f4f71c (current diff) 2c5df42999dd (diff) |
children | cb70ed101b5f |
files | agent/make/bugspot.bat agent/src/share/classes/sun/jvm/hotspot/asm/amd64/AMD64FloatRegister.java agent/src/share/classes/sun/jvm/hotspot/bugspot/BugSpot.java agent/src/share/classes/sun/jvm/hotspot/bugspot/BugSpotAgent.java agent/src/share/classes/sun/jvm/hotspot/bugspot/JavaLineNumberInfo.java agent/src/share/classes/sun/jvm/hotspot/bugspot/Main.java agent/src/share/classes/sun/jvm/hotspot/bugspot/PCFinder.java agent/src/share/classes/sun/jvm/hotspot/bugspot/PackageScanner.java agent/src/share/classes/sun/jvm/hotspot/bugspot/RegisterPanel.java agent/src/share/classes/sun/jvm/hotspot/bugspot/StackTraceEntry.java agent/src/share/classes/sun/jvm/hotspot/bugspot/StackTracePanel.java agent/src/share/classes/sun/jvm/hotspot/bugspot/ThreadListPanel.java agent/src/share/classes/sun/jvm/hotspot/bugspot/VariablePanel.java agent/src/share/classes/sun/jvm/hotspot/bugspot/tree/AddressTreeNodeAdapter.java agent/src/share/classes/sun/jvm/hotspot/bugspot/tree/DoubleTreeNodeAdapter.java agent/src/share/classes/sun/jvm/hotspot/bugspot/tree/EnumTreeNodeAdapter.java agent/src/share/classes/sun/jvm/hotspot/bugspot/tree/FieldTreeNodeAdapter.java agent/src/share/classes/sun/jvm/hotspot/bugspot/tree/FloatTreeNodeAdapter.java agent/src/share/classes/sun/jvm/hotspot/bugspot/tree/LongTreeNodeAdapter.java agent/src/share/classes/sun/jvm/hotspot/bugspot/tree/ObjectTreeNodeAdapter.java agent/src/share/classes/sun/jvm/hotspot/livejvm/BreakpointEvent.java agent/src/share/classes/sun/jvm/hotspot/livejvm/CIntegerAccessor.java agent/src/share/classes/sun/jvm/hotspot/livejvm/CStringAccessor.java agent/src/share/classes/sun/jvm/hotspot/livejvm/Event.java agent/src/share/classes/sun/jvm/hotspot/livejvm/ExceptionEvent.java agent/src/share/classes/sun/jvm/hotspot/livejvm/JNIHandleAccessor.java agent/src/share/classes/sun/jvm/hotspot/livejvm/ServiceabilityAgentJVMDIModule.java agent/src/share/classes/sun/jvm/hotspot/memory/BinaryTreeDictionary.java agent/src/share/classes/sun/jvm/hotspot/tools/PermStat.java agent/src/share/native/jvmdi/sa.cpp agent/src/share/native/jvmdi/sa.dsp agent/src/share/native/jvmdi/sa.dsw agent/src/share/native/jvmdi/sa.hpp graal/com.oracle.graal.amd64/src/com/oracle/graal/amd64/AMD64Address.java graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Address.java graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64DirectCallOp.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoopSafepointInsertionPhase.java graal/com.oracle.graal.ptx/src/com/oracle/graal/ptx/PTXAddress.java make/bsd/makefiles/wb.make make/linux/makefiles/wb.make make/solaris/makefiles/kernel.make make/solaris/makefiles/wb.make make/windows/makefiles/wb.make mx/projects src/share/tools/whitebox/sun/hotspot/WhiteBox.java src/share/tools/whitebox/sun/hotspot/parser/DiagnosticCommand.java src/share/vm/utilities/machineCodePrinter.cpp src/share/vm/utilities/machineCodePrinter.hpp test/runtime/7158988/TestFieldMonitor.sh |
diffstat | 625 files changed, 19141 insertions(+), 13373 deletions(-) [+] |
line wrap: on
line diff
--- a/.hgignore Tue Mar 12 11:38:24 2013 +0100 +++ b/.hgignore Tue Mar 12 11:38:52 2013 +0100 @@ -7,7 +7,7 @@ ^dist/ ^java/ ^lib/ -^jdk1.7.0 +^jdk1.(7|8).0 ^java64/ ^work/ \.checkstyle$
--- a/.hgtags Tue Mar 12 11:38:24 2013 +0100 +++ b/.hgtags Tue Mar 12 11:38:52 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
--- a/agent/make/Makefile Tue Mar 12 11:38:24 2013 +0100 +++ b/agent/make/Makefile Tue Mar 12 11:38:52 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
--- a/agent/make/bugspot.bat Tue Mar 12 11:38:24 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
--- a/agent/make/marks_notes.html Tue Mar 12 11:38:24 2013 +0100 +++ b/agent/make/marks_notes.html Tue Mar 12 11:38:52 2013 +0100 @@ -26,14 +26,12 @@ <ul> <li><code>java -cp classes sun.jvm.hotspot.HSDB</code> - <li><code>java -cp classes sun.jvm.hotspot.bugspot.Main</code> </ul> <h2>Feedback</h2> <p> 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. <p> 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:<br> @@ -47,7 +45,7 @@ </ul> <p> - 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 <code>javax.swing.Actions</code> architecture. <h2>Tasklist</h2> @@ -55,11 +53,7 @@ <p> <b>Stack memory pane</b>: 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. <p> <b>Integrations with the NetBeans architecture (plug in).</b> See the <a href="http://openide.netbeans.org">Netbeans Open APIs homepage</a>
--- a/agent/src/os/bsd/MacosxDebuggerLocal.m Tue Mar 12 11:38:24 2013 +0100 +++ b/agent/src/os/bsd/MacosxDebuggerLocal.m Tue Mar 12 11:38:52 2013 +0100 @@ -38,6 +38,8 @@ #import <dlfcn.h> #import <limits.h> #import <errno.h> +#import <sys/types.h> +#import <sys/ptrace.h> 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);
--- a/agent/src/os/bsd/libproc_impl.c Tue Mar 12 11:38:24 2013 +0100 +++ b/agent/src/os/bsd/libproc_impl.c Tue Mar 12 11:38:52 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; }
--- a/agent/src/os/bsd/libproc_impl.h Tue Mar 12 11:38:24 2013 +0100 +++ b/agent/src/os/bsd/libproc_impl.h Tue Mar 12 11:38:52 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);
--- a/agent/src/os/bsd/ps_proc.c Tue Mar 12 11:38:24 2013 +0100 +++ b/agent/src/os/bsd/ps_proc.c Tue Mar 12 11:38:52 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); } }
--- a/agent/src/os/linux/LinuxDebuggerLocal.c Tue Mar 12 11:38:24 2013 +0100 +++ b/agent/src/os/linux/LinuxDebuggerLocal.c Tue Mar 12 11:38:52 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
--- a/agent/src/os/linux/libproc.h Tue Mar 12 11:38:24 2013 +0100 +++ b/agent/src/os/linux/libproc.h Tue Mar 12 11:38:52 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
--- a/agent/src/os/linux/libproc_impl.c Tue Mar 12 11:38:24 2013 +0100 +++ b/agent/src/os/linux/libproc_impl.c Tue Mar 12 11:38:52 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; }
--- a/agent/src/os/linux/libproc_impl.h Tue Mar 12 11:38:24 2013 +0100 +++ b/agent/src/os/linux/libproc_impl.h Tue Mar 12 11:38:52 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);
--- a/agent/src/os/linux/ps_proc.c Tue Mar 12 11:38:24 2013 +0100 +++ b/agent/src/os/linux/ps_proc.c Tue Mar 12 11:38:52 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 <stdio.h> #include <stdlib.h> #include <string.h> +#include <signal.h> #include <errno.h> #include <sys/ptrace.h> #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); } }
--- a/agent/src/os/win32/windbg/sawindbg.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/agent/src/os/win32/windbg/sawindbg.cpp Tue Mar 12 11:38:52 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;
--- a/agent/src/share/classes/sun/jvm/hotspot/asm/amd64/AMD64FloatRegister.java Tue Mar 12 11:38:24 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); - } - -}
--- a/agent/src/share/classes/sun/jvm/hotspot/bugspot/BugSpot.java Tue Mar 12 11:38:24 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 <JMenuItem> */ - 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/*<LineNumberInfo>*/ - 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/*<Editor>*/ 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"); - } - } - } - } - } - } -}
--- a/agent/src/share/classes/sun/jvm/hotspot/bugspot/BugSpotAgent.java Tue Mar 12 11:38:24 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.*; - -/** <P> 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. </P> - * - * <P> 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. </P> - * - * <P> The BugSpot debugger requires that the underlying Debugger - * support C/C++ debugging via the CDebugger interface. </P> - * - * <P> FIXME: especially with the addition of remote debugging, this - * has turned into a mess; needs rethinking. </P> */ - -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=<path-to-dbx-executable>\n" + - " Default is derived from dbxPathPrefix"); - System.out.println(" or"); - System.out.println(" -DdbxPathPrefix=<xxx>\n" + - " where xxx is the path name of a dir structure that contains:\n" + - " <os>/<arch>/bin/dbx\n" + - " The default is " + defaultDbxPathPrefix); - System.out.println(" and"); - System.out.println(" -DdbxSvcAgentDSOPathName=<path-to-dbx-serviceability-agent-module>\n" + - " Default is determined from dbxSvcAgentDSOPathPrefix"); - System.out.println(" or"); - System.out.println(" -DdbxSvcAgentDSOPathPrefix=<xxx>\n" + - " where xxx is the pathname of a dir structure that contains:\n" + - " <os>/<arch>/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); - } - } -}
--- a/agent/src/share/classes/sun/jvm/hotspot/bugspot/JavaLineNumberInfo.java Tue Mar 12 11:38:24 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; } -}
--- a/agent/src/share/classes/sun/jvm/hotspot/bugspot/Main.java Tue Mar 12 11:38:24 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); - } -}
--- a/agent/src/share/classes/sun/jvm/hotspot/bugspot/PCFinder.java Tue Mar 12 11:38:24 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); - } -}
--- a/agent/src/share/classes/sun/jvm/hotspot/bugspot/PackageScanner.java Tue Mar 12 11:38:24 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); - } -}
--- a/agent/src/share/classes/sun/jvm/hotspot/bugspot/RegisterPanel.java Tue Mar 12 11:38:24 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/*<RegisterInfo>*/ 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); - } - } -}
--- a/agent/src/share/classes/sun/jvm/hotspot/bugspot/StackTraceEntry.java Tue Mar 12 11:38:24 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 = "<unknown>"; - 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(); - } - } -}
--- a/agent/src/share/classes/sun/jvm/hotspot/bugspot/StackTracePanel.java Tue Mar 12 11:38:24 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()); - } - } - } -}
--- a/agent/src/share/classes/sun/jvm/hotspot/bugspot/ThreadListPanel.java Tue Mar 12 11:38:24 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 = "<unknown>"; - 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<ThreadInfo> - private java.util.List threadList; - private JTable table; - private AbstractTableModel dataModel; - // List<Listener> - 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/*<ThreadProxy>*/ 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 "<no frames on stack>"; - } - 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); - } -}
--- a/agent/src/share/classes/sun/jvm/hotspot/bugspot/VariablePanel.java Tue Mar 12 11:38:24 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 "<Bad oop>"; - } - }; - } - 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)); - } - } -}
--- a/agent/src/share/classes/sun/jvm/hotspot/bugspot/tree/AddressTreeNodeAdapter.java Tue Mar 12 11:38:24 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"; - } -}
--- a/agent/src/share/classes/sun/jvm/hotspot/bugspot/tree/DoubleTreeNodeAdapter.java Tue Mar 12 11:38:24 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); - } -}
--- a/agent/src/share/classes/sun/jvm/hotspot/bugspot/tree/EnumTreeNodeAdapter.java Tue Mar 12 11:38:24 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); - } - } -}
--- a/agent/src/share/classes/sun/jvm/hotspot/bugspot/tree/FieldTreeNodeAdapter.java Tue Mar 12 11:38:24 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(); - } - } - } -}
--- a/agent/src/share/classes/sun/jvm/hotspot/bugspot/tree/FloatTreeNodeAdapter.java Tue Mar 12 11:38:24 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); - } -}
--- a/agent/src/share/classes/sun/jvm/hotspot/bugspot/tree/LongTreeNodeAdapter.java Tue Mar 12 11:38:24 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); - } -}
--- a/agent/src/share/classes/sun/jvm/hotspot/bugspot/tree/ObjectTreeNodeAdapter.java Tue Mar 12 11:38:24 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; } - } -}
--- a/agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/BsdDebugger.java Tue Mar 12 11:38:24 2013 +0100 +++ b/agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/BsdDebugger.java Tue Mar 12 11:38:52 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;
--- a/agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/BsdDebuggerLocal.java Tue Mar 12 11:38:24 2013 +0100 +++ b/agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/BsdDebuggerLocal.java Tue Mar 12 11:38:52 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; }
--- a/agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/BsdThread.java Tue Mar 12 11:38:24 2013 +0100 +++ b/agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/BsdThread.java Tue Mar 12 11:38:52 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]);
--- a/agent/src/share/classes/sun/jvm/hotspot/debugger/windbg/amd64/WindbgAMD64Thread.java Tue Mar 12 11:38:24 2013 +0100 +++ b/agent/src/share/classes/sun/jvm/hotspot/debugger/windbg/amd64/WindbgAMD64Thread.java Tue Mar 12 11:38:52 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) {
--- a/agent/src/share/classes/sun/jvm/hotspot/debugger/windbg/x86/WindbgX86Thread.java Tue Mar 12 11:38:24 2013 +0100 +++ b/agent/src/share/classes/sun/jvm/hotspot/debugger/windbg/x86/WindbgX86Thread.java Tue Mar 12 11:38:52 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) {
--- a/agent/src/share/classes/sun/jvm/hotspot/livejvm/BreakpointEvent.java Tue Mar 12 11:38:24 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; } -}
--- a/agent/src/share/classes/sun/jvm/hotspot/livejvm/CIntegerAccessor.java Tue Mar 12 11:38:24 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); - } -}
--- a/agent/src/share/classes/sun/jvm/hotspot/livejvm/CStringAccessor.java Tue Mar 12 11:38:24 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"); - } - } -}
--- a/agent/src/share/classes/sun/jvm/hotspot/livejvm/Event.java Tue Mar 12 11:38:24 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; } -}
--- a/agent/src/share/classes/sun/jvm/hotspot/livejvm/ExceptionEvent.java Tue Mar 12 11:38:24 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; } -}
--- a/agent/src/share/classes/sun/jvm/hotspot/livejvm/JNIHandleAccessor.java Tue Mar 12 11:38:24 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()); - } -}
--- a/agent/src/share/classes/sun/jvm/hotspot/livejvm/ServiceabilityAgentJVMDIModule.java Tue Mar 12 11:38:24 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; - } -}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/agent/src/share/classes/sun/jvm/hotspot/memory/AFLBinaryTreeDictionary.java Tue Mar 12 11:38:52 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); + } +}
--- a/agent/src/share/classes/sun/jvm/hotspot/memory/BinaryTreeDictionary.java Tue Mar 12 11:38:24 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); - } -}
--- a/agent/src/share/classes/sun/jvm/hotspot/memory/CMSCollector.java Tue Mar 12 11:38:24 2013 +0100 +++ b/agent/src/share/classes/sun/jvm/hotspot/memory/CMSCollector.java Tue Mar 12 11:38:52 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; } }
--- a/agent/src/share/classes/sun/jvm/hotspot/memory/CompactibleFreeListSpace.java Tue Mar 12 11:38:24 2013 +0100 +++ b/agent/src/share/classes/sun/jvm/hotspot/memory/CompactibleFreeListSpace.java Tue Mar 12 11:38:52 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));
--- a/agent/src/share/classes/sun/jvm/hotspot/memory/FreeList.java Tue Mar 12 11:38:24 2013 +0100 +++ b/agent/src/share/classes/sun/jvm/hotspot/memory/FreeList.java Tue Mar 12 11:38:52 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<FreeChunk>"); sizeField = type.getCIntegerField("_size"); countField = type.getCIntegerField("_count"); headerSize = type.getSize();
--- a/agent/src/share/classes/sun/jvm/hotspot/oops/ConstMethod.java Tue Mar 12 11:38:24 2013 +0100 +++ b/agent/src/share/classes/sun/jvm/hotspot/oops/ConstMethod.java Tue Mar 12 11:38:52 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(); } }
--- a/agent/src/share/classes/sun/jvm/hotspot/oops/ConstantPool.java Tue Mar 12 11:38:24 2013 +0100 +++ b/agent/src/share/classes/sun/jvm/hotspot/oops/ConstantPool.java Tue Mar 12 11:38:52 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); }
--- a/agent/src/share/classes/sun/jvm/hotspot/oops/MethodData.java Tue Mar 12 11:38:24 2013 +0100 +++ b/agent/src/share/classes/sun/jvm/hotspot/oops/MethodData.java Tue Mar 12 11:38:52 2013 +0100 @@ -184,7 +184,6 @@ if (trapReasonName[index] == null) { throw new InternalError("missing reason for " + index); } - System.out.println(trapReasonName[index]); } }
--- a/agent/src/share/classes/sun/jvm/hotspot/oops/ObjectHeap.java Tue Mar 12 11:38:24 2013 +0100 +++ b/agent/src/share/classes/sun/jvm/hotspot/oops/ObjectHeap.java Tue Mar 12 11:38:52 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()); } } }
--- a/agent/src/share/classes/sun/jvm/hotspot/runtime/ClassConstants.java Tue Mar 12 11:38:24 2013 +0100 +++ b/agent/src/share/classes/sun/jvm/hotspot/runtime/ClassConstants.java Tue Mar 12 11:38:52 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;
--- a/agent/src/share/classes/sun/jvm/hotspot/runtime/OSThread.java Tue Mar 12 11:38:24 2013 +0100 +++ b/agent/src/share/classes/sun/jvm/hotspot/runtime/OSThread.java Tue Mar 12 11:38:52 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); + } + }
--- a/agent/src/share/classes/sun/jvm/hotspot/runtime/ThreadLocalAllocBuffer.java Tue Mar 12 11:38:24 2013 +0100 +++ b/agent/src/share/classes/sun/jvm/hotspot/runtime/ThreadLocalAllocBuffer.java Tue Mar 12 11:38:52 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.*; /** <P> 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
--- a/agent/src/share/classes/sun/jvm/hotspot/runtime/VM.java Tue Mar 12 11:38:24 2013 +0100 +++ b/agent/src/share/classes/sun/jvm/hotspot/runtime/VM.java Tue Mar 12 11:38:52 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) {
--- a/agent/src/share/classes/sun/jvm/hotspot/runtime/bsd_amd64/BsdAMD64JavaThreadPDAccess.java Tue Mar 12 11:38:24 2013 +0100 +++ b/agent/src/share/classes/sun/jvm/hotspot/runtime/bsd_amd64/BsdAMD64JavaThreadPDAccess.java Tue Mar 12 11:38:52 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); } }
--- a/agent/src/share/classes/sun/jvm/hotspot/runtime/win32_amd64/Win32AMD64JavaThreadPDAccess.java Tue Mar 12 11:38:24 2013 +0100 +++ b/agent/src/share/classes/sun/jvm/hotspot/runtime/win32_amd64/Win32AMD64JavaThreadPDAccess.java Tue Mar 12 11:38:52 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); } }
--- a/agent/src/share/classes/sun/jvm/hotspot/runtime/win32_x86/Win32X86JavaThreadPDAccess.java Tue Mar 12 11:38:24 2013 +0100 +++ b/agent/src/share/classes/sun/jvm/hotspot/runtime/win32_x86/Win32X86JavaThreadPDAccess.java Tue Mar 12 11:38:52 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); } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/agent/src/share/classes/sun/jvm/hotspot/tools/ClassLoaderStats.java Tue Mar 12 11:38:52 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<ClassData> + } + + 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("<bootstrap>"); + 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("<internal>"); + + 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; + } +}
--- a/agent/src/share/classes/sun/jvm/hotspot/tools/HeapSummary.java Tue Mar 12 11:38:24 2013 +0100 +++ b/agent/src/share/classes/sun/jvm/hotspot/tools/HeapSummary.java Tue Mar 12 11:38:52 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:");
--- a/agent/src/share/classes/sun/jvm/hotspot/tools/JMap.java Tue Mar 12 11:38:24 2013 +0100 +++ b/agent/src/share/classes/sun/jvm/hotspot/tools/JMap.java Tue Mar 12 11:38:52 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 {
--- a/agent/src/share/classes/sun/jvm/hotspot/tools/PMap.java Tue Mar 12 11:38:24 2013 +0100 +++ b/agent/src/share/classes/sun/jvm/hotspot/tools/PMap.java Tue Mar 12 11:38:52 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);
--- a/agent/src/share/classes/sun/jvm/hotspot/tools/PStack.java Tue Mar 12 11:38:24 2013 +0100 +++ b/agent/src/share/classes/sun/jvm/hotspot/tools/PStack.java Tue Mar 12 11:38:52 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("<interpreter> "); - 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("<Unknown compiled code>"); - } - } else if (cb.isBufferBlob()) { - out.println("<StubRoutines>"); - } else if (cb.isRuntimeStub()) { - out.println("<RuntimeStub>"); - } else if (cb.isDeoptimizationStub()) { - out.println("<DeoptimizationStub>"); - } else if (cb.isUncommonTrapStub()) { - out.println("<UncommonTrap>"); - } else if (cb.isExceptionStub()) { - out.println("<ExceptionStub>"); - } else if (cb.isSafepointStub()) { - out.println("<SafepointStub>"); - } else { - out.println("<Unknown code blob>"); - } - } 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("<interpreter> "); + 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("<Unknown compiled code>"); + } + } else if (cb.isBufferBlob()) { + out.println("<StubRoutines>"); + } else if (cb.isRuntimeStub()) { + out.println("<RuntimeStub>"); + } else if (cb.isDeoptimizationStub()) { + out.println("<DeoptimizationStub>"); + } else if (cb.isUncommonTrapStub()) { + out.println("<UncommonTrap>"); + } else if (cb.isExceptionStub()) { + out.println("<ExceptionStub>"); + } else if (cb.isSafepointStub()) { + out.println("<SafepointStub>"); + } else { + out.println("<Unknown code blob>"); + } + } 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);
--- a/agent/src/share/classes/sun/jvm/hotspot/tools/PermStat.java Tue Mar 12 11:38:24 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<ClassData> - } - - 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("<bootstrap>"); - 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("<internal>"); - - 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; - } -}
--- a/agent/src/share/classes/sun/jvm/hotspot/tools/Tool.java Tue Mar 12 11:38:24 2013 +0100 +++ b/agent/src/share/classes/sun/jvm/hotspot/tools/Tool.java Tue Mar 12 11:38:52 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(); } }
--- a/agent/src/share/classes/sun/jvm/hotspot/ui/SAPanel.java Tue Mar 12 11:38:24 2013 +0100 +++ b/agent/src/share/classes/sun/jvm/hotspot/ui/SAPanel.java Tue Mar 12 11:38:52 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();
--- a/agent/src/share/classes/sun/jvm/hotspot/utilities/ConstantTag.java Tue Mar 12 11:38:24 2013 +0100 +++ b/agent/src/share/classes/sun/jvm/hotspot/utilities/ConstantTag.java Tue Mar 12 11:38:52 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);
--- a/agent/src/share/classes/sun/jvm/hotspot/utilities/soql/sa.js Tue Mar 12 11:38:24 2013 +0100 +++ b/agent/src/share/classes/sun/jvm/hotspot/utilities/soql/sa.js Tue Mar 12 11:38:52 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;
--- a/agent/src/share/native/jvmdi/sa.cpp Tue Mar 12 11:38:24 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 <stdio.h> -#include <stdarg.h> -#include <stdlib.h> -#include <vector> -#include "sa.hpp" -#include "jni.h" -#include "jvmdi.h" - -#ifndef WIN32 - #include <inttypes.h> -#else - typedef int int32_t; -#endif - -#ifdef WIN32 - #include <windows.h> - #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<jthread> 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, "<error>", SA_CMD_BUF_SIZE); - strncpy(saCmdBkptResMethodSig, "<error>", 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, "<init>", "(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; -} -};
--- a/agent/src/share/native/jvmdi/sa.dsp Tue Mar 12 11:38:24 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
--- a/agent/src/share/native/jvmdi/sa.dsw Tue Mar 12 11:38:24 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> -{{{ -}}} - -############################################################################### -
--- a/agent/src/share/native/jvmdi/sa.hpp Tue Mar 12 11:38:24 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); -}
--- a/graal/com.oracle.graal.alloc/src/com/oracle/graal/alloc/ComputeBlockOrder.java Tue Mar 12 11:38:24 2013 +0100 +++ b/graal/com.oracle.graal.alloc/src/com/oracle/graal/alloc/ComputeBlockOrder.java Tue Mar 12 11:38:52 2013 +0100 @@ -133,7 +133,7 @@ // scheduled. double unscheduledSum = 0.0; for (Block pred : mostLikelySuccessor.getPredecessors()) { - if (!visitedBlocks.get(pred.getId())) { + if (pred.getLinearScanNumber() == -1) { unscheduledSum += pred.getBeginNode().probability(); } }
--- a/graal/com.oracle.graal.amd64/src/com/oracle/graal/amd64/AMD64.java Tue Mar 12 11:38:24 2013 +0100 +++ b/graal/com.oracle.graal.amd64/src/com/oracle/graal/amd64/AMD64.java Tue Mar 12 11:38:52 2013 +0100 @@ -24,12 +24,11 @@ import static com.oracle.graal.api.code.MemoryBarriers.*; import static com.oracle.graal.api.code.Register.RegisterFlag.*; -import static com.oracle.graal.api.meta.Kind.*; import java.nio.*; import com.oracle.graal.api.code.*; -import com.oracle.graal.api.code.Register.*; +import com.oracle.graal.api.code.Register.RegisterFlag; /** * Represents the AMD64 architecture. @@ -106,8 +105,6 @@ rip }; - public static final RegisterValue RSP = rsp.asValue(Long); - public AMD64() { super("AMD64", 8,
--- a/graal/com.oracle.graal.amd64/src/com/oracle/graal/amd64/AMD64Address.java Tue Mar 12 11:38:24 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,203 +0,0 @@ -/* - * 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 - * 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.graal.amd64; - -import static com.oracle.graal.api.code.ValueUtil.*; - -import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; - -/** - * Represents an address in target machine memory, specified via some combination of a base - * register, an index register, a displacement and a scale. Note that the base and index registers - * may be a variable that will get a register assigned later by the register allocator. - */ -public final class AMD64Address extends Address { - - private static final long serialVersionUID = -4101548147426595051L; - - private final Value[] baseIndex; - private final Scale scale; - private final int displacement; - - /** - * Creates an {@link AMD64Address} with given base register, no scaling and no displacement. - * - * @param kind the kind of the value being addressed - * @param base the base register - */ - public AMD64Address(Kind kind, Value base) { - this(kind, base, ILLEGAL, Scale.Times1, 0); - } - - /** - * Creates an {@link AMD64Address} with given base register, no scaling and a given - * displacement. - * - * @param kind the kind of the value being addressed - * @param base the base register - * @param displacement the displacement - */ - public AMD64Address(Kind kind, Value base, int displacement) { - this(kind, base, ILLEGAL, Scale.Times1, displacement); - } - - /** - * Creates an {@link AMD64Address} with given base and index registers, scaling and - * displacement. This is the most general constructor. - * - * @param kind the kind of the value being addressed - * @param base the base register - * @param index the index register - * @param scale the scaling factor - * @param displacement the displacement - */ - public AMD64Address(Kind kind, Value base, Value index, Scale scale, int displacement) { - super(kind); - this.baseIndex = new Value[2]; - this.setBase(base); - this.setIndex(index); - this.scale = scale; - this.displacement = displacement; - - assert !isConstant(base) && !isStackSlot(base); - assert !isConstant(index) && !isStackSlot(index); - } - - /** - * A scaling factor used in the SIB addressing mode. - */ - public enum Scale { - Times1(1, 0), Times2(2, 1), Times4(4, 2), Times8(8, 3); - - private Scale(int value, int log2) { - this.value = value; - this.log2 = log2; - } - - /** - * The value (or multiplier) of this scale. - */ - public final int value; - - /** - * The {@linkplain #value value} of this scale log 2. - */ - public final int log2; - - public static Scale fromInt(int scale) { - switch (scale) { - case 1: - return Times1; - case 2: - return Times2; - case 4: - return Times4; - case 8: - return Times8; - default: - throw new IllegalArgumentException(String.valueOf(scale)); - } - } - } - - @Override - public Value[] components() { - return baseIndex; - } - - @Override - public String toString() { - StringBuilder s = new StringBuilder(); - s.append(getKind().getJavaName()).append("["); - String sep = ""; - if (isLegal(getBase())) { - s.append(getBase()); - sep = " + "; - } - if (isLegal(getIndex())) { - s.append(sep).append(getIndex()).append(" * ").append(getScale().value); - sep = " + "; - } - if (getDisplacement() < 0) { - s.append(" - ").append(-getDisplacement()); - } else if (getDisplacement() > 0) { - s.append(sep).append(getDisplacement()); - } - s.append("]"); - return s.toString(); - } - - @Override - public boolean equals(Object obj) { - if (obj instanceof AMD64Address) { - AMD64Address addr = (AMD64Address) obj; - return getKind() == addr.getKind() && getDisplacement() == addr.getDisplacement() && getBase().equals(addr.getBase()) && getScale() == addr.getScale() && - getIndex().equals(addr.getIndex()); - } - return false; - } - - @Override - public int hashCode() { - return getBase().hashCode() ^ getIndex().hashCode() ^ (getDisplacement() << 4) ^ (getScale().value << 8) ^ (getKind().ordinal() << 12); - } - - /** - * @return Base register that defines the start of the address computation. If not present, is - * denoted by {@link Value#ILLEGAL}. - */ - public Value getBase() { - return baseIndex[0]; - } - - public void setBase(Value base) { - this.baseIndex[0] = base; - } - - /** - * @return Index register, the value of which (possibly scaled by {@link #scale}) is added to - * {@link #getBase}. If not present, is denoted by {@link Value#ILLEGAL}. - */ - public Value getIndex() { - return baseIndex[1]; - } - - public void setIndex(Value index) { - this.baseIndex[1] = index; - } - - /** - * @return Scaling factor for indexing, dependent on target operand size. - */ - public Scale getScale() { - return scale; - } - - /** - * @return Optional additive displacement. - */ - public int getDisplacement() { - return displacement; - } -}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/AbstractAddress.java Tue Mar 12 11:38:52 2013 +0100 @@ -0,0 +1,29 @@ +/* + * 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.graal.api.code; + +/** + * Abstract base class that represents a platform specific address. + */ +public abstract class AbstractAddress { +}
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Address.java Tue Mar 12 11:38:24 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,44 +0,0 @@ -/* - * 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 - * 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.graal.api.code; - -import com.oracle.graal.api.meta.*; - -/** - * Base class to represent an address in target machine memory. The concrete representation of the - * address is platform dependent. - */ -public abstract class Address extends Value { - - private static final long serialVersionUID = -1003772042519945089L; - - public Address(Kind kind) { - super(kind); - } - - /** - * The values that this address is composed of. Used by the register allocator to manipulate - * addresses in a platform independent way. - */ - public abstract Value[] components(); -}
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/DebugInfo.java Tue Mar 12 11:38:24 2013 +0100 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/DebugInfo.java Tue Mar 12 11:38:52 2013 +0100 @@ -36,6 +36,7 @@ private final BytecodePosition bytecodePosition; private final BitSet registerRefMap; private final BitSet frameRefMap; + private final short deoptimizationReason; /** * Creates a new {@link DebugInfo} from the given values. @@ -45,10 +46,11 @@ * @param registerRefMap the register map * @param frameRefMap the reference map for {@code frame}, which may be {@code null} */ - public DebugInfo(BytecodePosition codePos, BitSet registerRefMap, BitSet frameRefMap) { + public DebugInfo(BytecodePosition codePos, BitSet registerRefMap, BitSet frameRefMap, short deoptimizationReason) { this.bytecodePosition = codePos; this.registerRefMap = registerRefMap; this.frameRefMap = frameRefMap; + this.deoptimizationReason = deoptimizationReason; } /** @@ -114,4 +116,13 @@ public BitSet getFrameRefMap() { return frameRefMap; } + + /** + * Identifies the reason in case a deoptimization happens at this program counter. + * + * @return the reason of the deoptimization + */ + public short getDeoptimizationReason() { + return deoptimizationReason; + } }
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/DisassemblerProvider.java Tue Mar 12 11:38:24 2013 +0100 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/DisassemblerProvider.java Tue Mar 12 11:38:52 2013 +0100 @@ -29,6 +29,10 @@ /** * Gets a textual disassembly of some given installed code. + * + * @return a non-zero length string containing a disassembly of {@code code} or null if + * {@code code} is {@link InstalledCode#isValid() invalid} or it could not be + * disassembled for some other reason */ String disassemble(InstalledCode code); }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/SpeculationLog.java Tue Mar 12 11:38:52 2013 +0100 @@ -0,0 +1,74 @@ +/* + * 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 com.oracle.graal.api.code; + +import java.util.*; + +import com.oracle.graal.api.meta.*; + +/** + * Manages a list of unique deoptimization reasons and returns a unique index for each reason. This + * class is not thread safe and assumes that at every point in time there is only a single Graal + * compilation accessing this object. + * + */ +public final class SpeculationLog { + + public static final int MAX_CACHE_SIZE = 1 << 15; + + private List<DeoptimizationReason> speculations = new ArrayList<>(); + private boolean[] map = new boolean[10]; + private Set<DeoptimizationReason> snapshot = new HashSet<>(); + + public short addSpeculation(DeoptimizationReason reason) { + short index = (short) speculations.indexOf(reason); + if (index != -1) { + // Nothing to add, reason already registered. + return index; + } + if (speculations.size() >= MAX_CACHE_SIZE) { + throw new BailoutException("Too many deoptimization reasons recorded"); + } + speculations.add(reason); + if (map.length < speculations.size()) { + map = Arrays.copyOf(map, map.length * 2); + } + return (short) (speculations.size() - 1); + } + + public boolean[] getRawMap() { + return map; + } + + public void snapshot() { + for (int i = 0; i < speculations.size(); ++i) { + if (map[i]) { + snapshot.add(speculations.get(i)); + } + } + } + + public boolean maySpeculate(DeoptimizationReason reason) { + return !snapshot.contains(reason); + } +}
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/ValueUtil.java Tue Mar 12 11:38:24 2013 +0100 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/ValueUtil.java Tue Mar 12 11:38:52 2013 +0100 @@ -78,16 +78,6 @@ return (StackSlot) value; } - public static boolean isAddress(Value value) { - assert value != null; - return value instanceof Address; - } - - public static Address asAddress(Value value) { - assert value != null; - return (Address) value; - } - public static boolean isRegister(Value value) { assert value != null; return value instanceof RegisterValue;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestBytecodeDisassemblerProvider.java Tue Mar 12 11:38:52 2013 +0100 @@ -0,0 +1,61 @@ +/* + * 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 com.oracle.graal.api.meta.test; + +import org.junit.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.api.runtime.*; + +/** + * Tests for {@link BytecodeDisassemblerProvider}. + */ +public class TestBytecodeDisassemblerProvider { + + public TestBytecodeDisassemblerProvider() { + } + + /** + * Tests that successive disassembling of the same method produces the same result. + */ + @Test + public void disassembleTest() { + BytecodeDisassemblerProvider dis = Graal.getRuntime().getCapability(BytecodeDisassemblerProvider.class); + if (dis != null) { + int count = 0; + for (ResolvedJavaMethod m : TestJavaMethod.methods.values()) { + String disasm1 = dis.disassemble(m); + String disasm2 = dis.disassemble(m); + if (disasm1 == null) { + Assert.assertTrue(disasm2 == null); + } else { + Assert.assertTrue(String.valueOf(m), disasm1.length() > 0); + Assert.assertEquals(String.valueOf(m), disasm1, disasm2); + } + if (count++ > 20) { + break; + } + } + } + } +}
--- a/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestResolvedJavaMethod.java Tue Mar 12 11:38:24 2013 +0100 +++ b/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestResolvedJavaMethod.java Tue Mar 12 11:38:52 2013 +0100 @@ -49,11 +49,14 @@ for (Map.Entry<Method, ResolvedJavaMethod> e : methods.entrySet()) { ResolvedJavaMethod m = e.getValue(); byte[] code = m.getCode(); - assertNotNull(code); - if (isAbstract(m.getModifiers())) { - assertTrue(code.length == 0); - } else if (!isNative(m.getModifiers())) { - assertTrue(code.length > 0); + if (code == null) { + assertTrue(m.getCodeSize() == 0); + } else { + if (isAbstract(m.getModifiers())) { + assertTrue(code.length == 0); + } else if (!isNative(m.getModifiers())) { + assertTrue(code.length > 0); + } } } }
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/BytecodeDisassemblerProvider.java Tue Mar 12 11:38:24 2013 +0100 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/BytecodeDisassemblerProvider.java Tue Mar 12 11:38:52 2013 +0100 @@ -28,7 +28,11 @@ public interface BytecodeDisassemblerProvider { /** - * Gets a textual disassembly of the bytecode for a given method. + * Gets a textual disassembly of the bytecode for a given method. In the absence of bytecode + * rewriting, disassembling a method will produce the same result. + * + * @return a non-zero length string containing a disassembly of {@code method}'s bytecode or + * null if {@code method} has no bytecode (i.e., {@code method.getCodeSize() == 0}) */ String disassemble(ResolvedJavaMethod method); }
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaMethod.java Tue Mar 12 11:38:24 2013 +0100 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaMethod.java Tue Mar 12 11:38:52 2013 +0100 @@ -34,18 +34,18 @@ public interface ResolvedJavaMethod extends JavaMethod, InvokeTarget { /** - * Returns the bytecodes of this method, if the method has code. The returned byte array does - * not contain breakpoints or non-Java bytecodes. + * Returns the bytecode of this method, if the method has code. The returned byte array does not + * contain breakpoints or non-Java bytecodes. * - * @return the bytecodes of the method, or {@code null} if none is available + * @return the bytecode of the method, or {@code null} if {@code getCodeSize() == 0} */ byte[] getCode(); /** - * Returns the size of the bytecodes of this method, if the method has code. This is equivalent + * Returns the size of the bytecode of this method, if the method has code. This is equivalent * to {@link #getCode()}. {@code length} if the method has code. * - * @return the size of the bytecodes in bytes, or 0 if no bytecodes is available + * @return the size of the bytecode in bytes, or 0 if no bytecode is available */ int getCodeSize(); @@ -175,5 +175,4 @@ * Returns the localvariable table of this method. */ LocalVariableTable getLocalVariableTable(); - }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64Address.java Tue Mar 12 11:38:52 2013 +0100 @@ -0,0 +1,163 @@ +/* + * 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 + * 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.graal.asm.amd64; + +import com.oracle.graal.api.code.*; + +/** + * Represents an address in target machine memory, specified via some combination of a base + * register, an index register, a displacement and a scale. Note that the base and index registers + * may be a variable that will get a register assigned later by the register allocator. + */ +public final class AMD64Address extends AbstractAddress { + + private final Register base; + private final Register index; + private final Scale scale; + private final int displacement; + + /** + * Creates an {@link AMD64Address} with given base register, no scaling and no displacement. + * + * @param base the base register + */ + public AMD64Address(Register base) { + this(base, Register.None, Scale.Times1, 0); + } + + /** + * Creates an {@link AMD64Address} with given base register, no scaling and a given + * displacement. + * + * @param base the base register + * @param displacement the displacement + */ + public AMD64Address(Register base, int displacement) { + this(base, Register.None, Scale.Times1, displacement); + } + + /** + * Creates an {@link AMD64Address} with given base and index registers, scaling and + * displacement. This is the most general constructor. + * + * @param base the base register + * @param index the index register + * @param scale the scaling factor + * @param displacement the displacement + */ + public AMD64Address(Register base, Register index, Scale scale, int displacement) { + this.base = base; + this.index = index; + this.scale = scale; + this.displacement = displacement; + } + + /** + * A scaling factor used in the SIB addressing mode. + */ + public enum Scale { + Times1(1, 0), Times2(2, 1), Times4(4, 2), Times8(8, 3); + + private Scale(int value, int log2) { + this.value = value; + this.log2 = log2; + } + + /** + * The value (or multiplier) of this scale. + */ + public final int value; + + /** + * The {@linkplain #value value} of this scale log 2. + */ + public final int log2; + + public static Scale fromInt(int scale) { + switch (scale) { + case 1: + return Times1; + case 2: + return Times2; + case 4: + return Times4; + case 8: + return Times8; + default: + throw new IllegalArgumentException(String.valueOf(scale)); + } + } + } + + @Override + public String toString() { + StringBuilder s = new StringBuilder(); + s.append("["); + String sep = ""; + if (getBase() != Register.None) { + s.append(getBase()); + sep = " + "; + } + if (getIndex() != Register.None) { + s.append(sep).append(getIndex()).append(" * ").append(getScale().value); + sep = " + "; + } + if (getDisplacement() < 0) { + s.append(" - ").append(-getDisplacement()); + } else if (getDisplacement() > 0) { + s.append(sep).append(getDisplacement()); + } + s.append("]"); + return s.toString(); + } + + /** + * @return Base register that defines the start of the address computation. If not present, is + * denoted by {@link Register#None}. + */ + public Register getBase() { + return base; + } + + /** + * @return Index register, the value of which (possibly scaled by {@link #getScale}) is added to + * {@link #getBase}. If not present, is denoted by {@link Register#None}. + */ + public Register getIndex() { + return index; + } + + /** + * @return Scaling factor for indexing, dependent on target operand size. + */ + public Scale getScale() { + return scale; + } + + /** + * @return Optional additive displacement. + */ + public int getDisplacement() { + return displacement; + } +}
--- a/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64Assembler.java Tue Mar 12 11:38:24 2013 +0100 +++ b/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64Assembler.java Tue Mar 12 11:38:52 2013 +0100 @@ -24,13 +24,11 @@ import static com.oracle.graal.amd64.AMD64.*; import static com.oracle.graal.api.code.MemoryBarriers.*; -import static com.oracle.graal.api.code.ValueUtil.*; import static com.oracle.graal.asm.NumUtil.*; import static com.oracle.graal.asm.amd64.AMD64AsmOptions.*; import com.oracle.graal.amd64.*; import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.*; /** @@ -38,19 +36,13 @@ */ public class AMD64Assembler extends AbstractAssembler { - /** - * The kind for pointers and raw registers. Since we know we are 64 bit here, we can hardcode - * it. - */ - private static final Kind Word = Kind.Long; - private static final int MinEncodingNeedsRex = 8; /** * A sentinel value used as a place holder in an instruction stream for an address that will be * patched. */ - private static final AMD64Address Placeholder = new AMD64Address(Kind.Illegal, rip.asValue()); + private static final AMD64Address Placeholder = new AMD64Address(rip); /** * The x86 condition codes used for conditional jumps/moves. @@ -203,16 +195,16 @@ } // immediate-to-memory forms - private void emitArithOperand(int op1, Register rm, AMD64Address adr, int imm32) { + private void emitArithOperand(int op1, int op2, AMD64Address adr, int imm32) { assert (op1 & 0x01) == 1 : "should be 32bit operation"; assert (op1 & 0x02) == 0 : "sign-extension bit should not be set"; if (isByte(imm32)) { emitByte(op1 | 0x02); // set sign bit - emitOperandHelper(rm, adr); + emitOperandHelper(op2, adr); emitByte(imm32 & 0xFF); } else { emitByte(op1); - emitOperandHelper(rm, adr); + emitOperandHelper(op2, adr); emitInt(imm32); } } @@ -224,8 +216,16 @@ } protected void emitOperandHelper(Register reg, AMD64Address addr) { - Register base = isLegal(addr.getBase()) ? asRegister(addr.getBase()) : Register.None; - Register index = isLegal(addr.getIndex()) ? asRegister(addr.getIndex()) : Register.None; + assert reg != Register.None; + emitOperandHelper(encode(reg), addr); + } + + protected void emitOperandHelper(int reg, AMD64Address addr) { + assert (reg & 0x07) == reg; + int regenc = reg << 3; + + Register base = addr.getBase(); + Register index = addr.getIndex(); AMD64Address.Scale scale = addr.getScale(); int disp = addr.getDisplacement(); @@ -235,11 +235,6 @@ base = frameRegister; } - // Encode the registers as needed in the fields they are used in - - assert reg != Register.None; - int regenc = encode(reg) << 3; - if (base == AMD64.rip) { // also matches Placeholder // [00 000 101] disp32 assert index == Register.None : "cannot use RIP relative addressing with index register"; @@ -331,7 +326,7 @@ public final void addl(AMD64Address dst, int imm32) { prefix(dst); - emitArithOperand(0x81, rax, dst, imm32); + emitArithOperand(0x81, 0, dst, imm32); } public final void addl(Register dst, int imm32) { @@ -445,6 +440,7 @@ public final void bsfq(Register dst, AMD64Address src) { prefixq(src, dst); + emitByte(0x0F); emitByte(0xBC); emitOperandHelper(dst, src); } @@ -458,6 +454,7 @@ public final void bsrq(Register dst, AMD64Address src) { prefixq(src, dst); + emitByte(0x0F); emitByte(0xBD); emitOperandHelper(dst, src); } @@ -471,6 +468,7 @@ public final void bsrl(Register dst, AMD64Address src) { prefix(src, dst); + emitByte(0x0F); emitByte(0xBD); emitOperandHelper(dst, src); } @@ -541,6 +539,15 @@ } } + public final void cvtsd2ss(Register dst, AMD64Address src) { + assert dst.isFpu(); + emitByte(0xF2); + prefix(src, dst); + emitByte(0x0F); + emitByte(0x5A); + emitOperandHelper(dst, src); + } + public final void cvtsd2ss(Register dst, Register src) { assert dst.isFpu(); assert src.isFpu(); @@ -551,6 +558,15 @@ emitByte(0xC0 | encode); } + public final void cvtsi2sdl(Register dst, AMD64Address src) { + assert dst.isFpu(); + emitByte(0xF2); + prefix(src, dst); + emitByte(0x0F); + emitByte(0x2A); + emitOperandHelper(dst, src); + } + public final void cvtsi2sdl(Register dst, Register src) { assert dst.isFpu(); emitByte(0xF2); @@ -560,6 +576,15 @@ emitByte(0xC0 | encode); } + public final void cvtsi2ssl(Register dst, AMD64Address src) { + assert dst.isFpu(); + emitByte(0xF3); + prefix(src, dst); + emitByte(0x0F); + emitByte(0x2A); + emitOperandHelper(dst, src); + } + public final void cvtsi2ssl(Register dst, Register src) { assert dst.isFpu(); emitByte(0xF3); @@ -569,6 +594,15 @@ emitByte(0xC0 | encode); } + public final void cvtss2sd(Register dst, AMD64Address src) { + assert dst.isFpu(); + emitByte(0xF3); + prefix(src, dst); + emitByte(0x0F); + emitByte(0x5A); + emitOperandHelper(dst, src); + } + public final void cvtss2sd(Register dst, Register src) { assert dst.isFpu(); assert src.isFpu(); @@ -579,6 +613,14 @@ emitByte(0xC0 | encode); } + public final void cvttsd2sil(Register dst, AMD64Address src) { + emitByte(0xF2); + prefix(src, dst); + emitByte(0x0F); + emitByte(0x2C); + emitOperandHelper(dst, src); + } + public final void cvttsd2sil(Register dst, Register src) { assert src.isFpu(); emitByte(0xF2); @@ -588,6 +630,14 @@ emitByte(0xC0 | encode); } + public final void cvttss2sil(Register dst, AMD64Address src) { + emitByte(0xF3); + prefix(src, dst); + emitByte(0x0F); + emitByte(0x2C); + emitOperandHelper(dst, src); + } + public final void cvttss2sil(Register dst, Register src) { assert src.isFpu(); emitByte(0xF3); @@ -600,7 +650,7 @@ protected final void decl(AMD64Address dst) { prefix(dst); emitByte(0xFF); - emitOperandHelper(rcx, dst); + emitOperandHelper(1, dst); } public final void divsd(Register dst, AMD64Address src) { @@ -664,6 +714,13 @@ emitByte(0xC0 | encode); } + public final void imull(Register dst, AMD64Address src) { + prefix(src, dst); + emitByte(0x0F); + emitByte(0xAF); + emitOperandHelper(dst, src); + } + public final void imull(Register dst, Register src, int value) { int encode = prefixAndEncode(dst.encoding, src.encoding); if (isByte(value)) { @@ -680,7 +737,7 @@ protected final void incl(AMD64Address dst) { prefix(dst); emitByte(0xFF); - emitOperandHelper(rax, dst); + emitOperandHelper(0, dst); } private void jcc(ConditionFlag cc, int jumpTarget, boolean forceDisp32) { @@ -856,7 +913,7 @@ public final void movb(AMD64Address dst, int imm8) { prefix(dst); emitByte(0xC6); - emitOperandHelper(rax, dst); + emitOperandHelper(0, dst); emitByte(imm8); } @@ -907,7 +964,7 @@ public final void movl(AMD64Address dst, int imm32) { prefix(dst); emitByte(0xC7); - emitOperandHelper(rax, dst); + emitOperandHelper(0, dst); emitInt(imm32); } @@ -1050,11 +1107,18 @@ emitByte(0xC0 | encode); } + public final void movsxw(Register dst, AMD64Address src) { + prefix(src, dst); + emitByte(0x0F); + emitByte(0xBF); + emitOperandHelper(dst, src); + } + public final void movw(AMD64Address dst, int imm16) { emitByte(0x66); // switch to 16-bit mode prefix(dst); emitByte(0xC7); - emitOperandHelper(rax, dst); + emitOperandHelper(0, dst); emitShort(imm16); } @@ -1461,15 +1525,7 @@ public final void subl(AMD64Address dst, int imm32) { prefix(dst); - if (isByte(imm32)) { - emitByte(0x83); - emitOperandHelper(rbp, dst); - emitByte(imm32 & 0xFF); - } else { - emitByte(0x81); - emitOperandHelper(rbp, dst); - emitInt(imm32); - } + emitArithOperand(0x81, 5, dst, imm32); } public final void subl(Register dst, int imm32) { @@ -1779,8 +1835,8 @@ } } - private static boolean needsRex(Value value) { - return isRegister(value) && asRegister(value).encoding >= MinEncodingNeedsRex; + private static boolean needsRex(Register reg) { + return reg.encoding >= MinEncodingNeedsRex; } private void prefix(AMD64Address adr) { @@ -1957,6 +2013,15 @@ emitOperandHelper(reg, adr); } + public final void cvtsi2sdq(Register dst, AMD64Address src) { + assert dst.isFpu(); + emitByte(0xF2); + prefixq(src, dst); + emitByte(0x0F); + emitByte(0x2A); + emitOperandHelper(dst, src); + } + public final void cvtsi2sdq(Register dst, Register src) { assert dst.isFpu(); emitByte(0xF2); @@ -1966,6 +2031,15 @@ emitByte(0xC0 | encode); } + public final void cvtsi2ssq(Register dst, AMD64Address src) { + assert dst.isFpu(); + emitByte(0xF3); + prefixq(src, dst); + emitByte(0x0F); + emitByte(0x2A); + emitOperandHelper(dst, src); + } + public final void cvtsi2ssq(Register dst, Register src) { assert dst.isFpu(); emitByte(0xF3); @@ -1975,6 +2049,14 @@ emitByte(0xC0 | encode); } + public final void cvttsd2siq(Register dst, AMD64Address src) { + emitByte(0xF2); + prefixq(src, dst); + emitByte(0x0F); + emitByte(0x2C); + emitOperandHelper(dst, src); + } + public final void cvttsd2siq(Register dst, Register src) { assert src.isFpu(); emitByte(0xF2); @@ -1984,6 +2066,14 @@ emitByte(0xC0 | encode); } + public final void cvttss2siq(Register dst, AMD64Address src) { + emitByte(0xF3); + prefixq(src, dst); + emitByte(0x0F); + emitByte(0x2C); + emitOperandHelper(dst, src); + } + public final void cvttss2siq(Register dst, Register src) { assert src.isFpu(); emitByte(0xF3); @@ -2003,7 +2093,7 @@ protected final void decq(AMD64Address dst) { prefixq(dst); emitByte(0xFF); - emitOperandHelper(rcx, dst); + emitOperandHelper(1, dst); } public final void divq(Register src) { @@ -2025,6 +2115,13 @@ emitByte(0xC0 | encode); } + public final void imulq(Register dst, AMD64Address src) { + prefixq(src, dst); + emitByte(0x0F); + emitByte(0xAF); + emitOperandHelper(dst, src); + } + public final void imulq(Register dst, Register src, int value) { int encode = prefixqAndEncode(dst.encoding, src.encoding); if (isByte(value)) { @@ -2078,7 +2175,7 @@ public final void movslq(AMD64Address dst, int imm32) { prefixq(dst); emitByte(0xC7); - emitOperandHelper(rax, dst); + emitOperandHelper(0, dst); emitInt(imm32); } @@ -2240,7 +2337,7 @@ // the code where this idiom is used, in particular the // orderAccess code. lock(); - addl(new AMD64Address(Word, RSP, 0), 0); // Assert the lock# signal here + addl(new AMD64Address(rsp, 0), 0); // Assert the lock# signal here } } } @@ -2281,7 +2378,7 @@ } public void nullCheck(Register r) { - testl(AMD64.rax, new AMD64Address(Word, r.asValue(Word), 0)); + testl(AMD64.rax, new AMD64Address(r, 0)); } @Override @@ -2319,7 +2416,7 @@ public final void fld(AMD64Address src) { emitByte(0xDD); - emitOperandHelper(rax, src); + emitOperandHelper(0, src); } public final void fldln2() { @@ -2339,7 +2436,7 @@ public final void fstp(AMD64Address src) { emitByte(0xDD); - emitOperandHelper(rbx, src); + emitOperandHelper(3, src); } public final void fsin() { @@ -2362,8 +2459,8 @@ } @Override - public AMD64Address makeAddress(Kind kind, Value base, int displacement) { - return new AMD64Address(kind, base, displacement); + public AMD64Address makeAddress(Register base, int displacement) { + return new AMD64Address(base, displacement); } @Override
--- a/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64MacroAssembler.java Tue Mar 12 11:38:24 2013 +0100 +++ b/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64MacroAssembler.java Tue Mar 12 11:38:52 2013 +0100 @@ -26,7 +26,6 @@ import com.oracle.graal.amd64.*; import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; /** * This class implements commonly used X86 code patterns. @@ -222,7 +221,7 @@ * volatile field! */ public final void movlong(AMD64Address dst, long src) { - AMD64Address high = new AMD64Address(dst.getKind(), dst.getBase(), dst.getIndex(), dst.getScale(), dst.getDisplacement() + 4); + AMD64Address high = new AMD64Address(dst.getBase(), dst.getIndex(), dst.getScale(), dst.getDisplacement() + 4); movl(dst, (int) (src & 0xFFFFFFFF)); movl(high, (int) (src >> 32)); } @@ -230,7 +229,7 @@ public final void flog(Register dest, Register value, boolean base10) { assert dest.isFpu() && value.isFpu(); - AMD64Address tmp = new AMD64Address(Kind.Double, AMD64.RSP); + AMD64Address tmp = new AMD64Address(AMD64.rsp); if (base10) { fldlg2(); } else { @@ -264,7 +263,7 @@ private AMD64Address trigPrologue(Register value) { assert value.isFpu(); - AMD64Address tmp = new AMD64Address(Kind.Double, AMD64.RSP); + AMD64Address tmp = new AMD64Address(AMD64.rsp); subq(AMD64.rsp, 8); movsd(tmp, value); fld(tmp); @@ -286,18 +285,16 @@ * @param frameToCSA offset from the frame pointer to the CSA */ public final void save(CalleeSaveLayout csl, int frameToCSA) { - RegisterValue frame = frameRegister.asValue(); for (Register r : csl.registers) { int offset = csl.offsetOf(r); - movq(new AMD64Address(target.wordKind, frame, frameToCSA + offset), r); + movq(new AMD64Address(frameRegister, frameToCSA + offset), r); } } public final void restore(CalleeSaveLayout csl, int frameToCSA) { - RegisterValue frame = frameRegister.asValue(); for (Register r : csl.registers) { int offset = csl.offsetOf(r); - movq(r, new AMD64Address(target.wordKind, frame, frameToCSA + offset)); + movq(r, new AMD64Address(frameRegister, frameToCSA + offset)); } } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.asm.ptx/src/com/oracle/graal/asm/ptx/PTXAddress.java Tue Mar 12 11:38:52 2013 +0100 @@ -0,0 +1,72 @@ +/* + * 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.graal.asm.ptx; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; + +/** + * Represents an address in target machine memory, specified via some combination of a base register + * and a displacement. + */ +public final class PTXAddress extends AbstractAddress { + + private final Register base; + private final long displacement; + + /** + * Creates an {@link PTXAddress} with given base register and no displacement. + * + * @param base the base register + */ + public PTXAddress(Register base) { + this(base, 0); + } + + /** + * Creates an {@link PTXAddress} with given base register and a displacement. This is the most + * general constructor. + * + * @param base the base register + * @param displacement the displacement + */ + public PTXAddress(Register base, long displacement) { + this.base = base; + this.displacement = displacement; + } + + /** + * @return Base register that defines the start of the address computation. If not present, is + * denoted by {@link Value#ILLEGAL}. + */ + public Register getBase() { + return base; + } + + /** + * @return Optional additive displacement. + */ + public long getDisplacement() { + return displacement; + } +}
--- a/graal/com.oracle.graal.asm.ptx/src/com/oracle/graal/asm/ptx/PTXAssembler.java Tue Mar 12 11:38:24 2013 +0100 +++ b/graal/com.oracle.graal.asm.ptx/src/com/oracle/graal/asm/ptx/PTXAssembler.java Tue Mar 12 11:38:52 2013 +0100 @@ -23,8 +23,6 @@ package com.oracle.graal.asm.ptx; import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; -import com.oracle.graal.ptx.*; public class PTXAssembler extends AbstractPTXAssembler { @@ -177,7 +175,7 @@ emitString("exit;" + " " + ""); } - public final void ld_global_b8(Register d, Register a, int immOff) { + public final void ld_global_b8(Register d, Register a, long immOff) { emitString("ld.global.b8" + " " + "%r" + d.encoding() + ", [%r" + a.encoding() + " + " + immOff + "]" + ";" + ""); } @@ -742,8 +740,8 @@ } @Override - public PTXAddress makeAddress(Kind kind, Value base, int displacement) { - return new PTXAddress(kind, base, displacement); + public PTXAddress makeAddress(Register base, int displacement) { + return new PTXAddress(base, displacement); } @Override
--- a/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAssembler.java Tue Mar 12 11:38:24 2013 +0100 +++ b/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAssembler.java Tue Mar 12 11:38:52 2013 +0100 @@ -23,7 +23,6 @@ package com.oracle.graal.asm.sparc; import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.*; import com.oracle.graal.sparc.*; @@ -55,13 +54,13 @@ } @Override - public Address makeAddress(Kind kind, Value base, int displacement) { + public AbstractAddress makeAddress(Register base, int displacement) { // SPARC: Implement address calculation. return null; } @Override - public Address getPlaceholder() { + public AbstractAddress getPlaceholder() { // SPARC: Implement address patching. return null; }
--- a/graal/com.oracle.graal.asm.test/src/com/oracle/graal/asm/test/AssemblerTest.java Tue Mar 12 11:38:24 2013 +0100 +++ b/graal/com.oracle.graal.asm.test/src/com/oracle/graal/asm/test/AssemblerTest.java Tue Mar 12 11:38:52 2013 +0100 @@ -54,7 +54,14 @@ Buffer codeBuffer = test.generateCode(compResult, codeCache.getTarget(), registerConfig, cc); compResult.setTargetCode(codeBuffer.close(true), codeBuffer.position()); - return codeCache.addMethod(method, compResult, null); + InstalledCode code = codeCache.addMethod(method, compResult, null); + + DisassemblerProvider dis = Graal.getRuntime().getCapability(DisassemblerProvider.class); + if (dis != null) { + String disasm = dis.disassemble(code); + Assert.assertTrue(String.valueOf(code.getMethod()), disasm == null || disasm.length() > 0); + } + return code; } protected Object runTest(String methodName, CodeGenTest test, Object... args) {
--- a/graal/com.oracle.graal.asm/src/com/oracle/graal/asm/AbstractAssembler.java Tue Mar 12 11:38:24 2013 +0100 +++ b/graal/com.oracle.graal.asm/src/com/oracle/graal/asm/AbstractAssembler.java Tue Mar 12 11:38:52 2013 +0100 @@ -25,7 +25,6 @@ import java.nio.*; import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; /** * The platform-independent base class for the assembler. @@ -87,12 +86,12 @@ /** * This is used by the TargetMethodAssembler to convert a {@link StackSlot} to an - * {@link Address}. + * {@link AbstractAddress}. */ - public abstract Address makeAddress(Kind kind, Value base, int displacement); + public abstract AbstractAddress makeAddress(Register base, int displacement); /** * Returns a target specific placeholder address that can be used for code patching. */ - public abstract Address getPlaceholder(); + public abstract AbstractAddress getPlaceholder(); }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.amd64.test/src/com/oracle/graal/compiler/amd64/test/AMD64AllocatorTest.java Tue Mar 12 11:38:52 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.graal.compiler.amd64.test; + +import org.junit.*; + +import com.oracle.graal.compiler.test.backend.*; + +public class AMD64AllocatorTest extends AllocatorTest { + + @Test + public void test1() { + test("test1snippet", 2, 1, 0); + } + + public static long test1snippet(long x) { + return x + 5; + } + + @Test + public void test2() { + test("test2snippet", 2, 0, 0); + } + + public static long test2snippet(long x) { + return x * 5; + } + + @Ignore + @Test + public void test3() { + test("test3snippet", 4, 1, 0); + } + + public static long test3snippet(long x) { + return x / 3 + x % 3; + } + +}
--- a/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64DeoptimizationStub.java Tue Mar 12 11:38:24 2013 +0100 +++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64DeoptimizationStub.java Tue Mar 12 11:38:52 2013 +0100 @@ -22,8 +22,6 @@ */ package com.oracle.graal.compiler.amd64; -import java.util.*; - import com.oracle.graal.api.code.*; import com.oracle.graal.api.code.RuntimeCallTarget.*; import com.oracle.graal.api.meta.*; @@ -32,43 +30,28 @@ import com.oracle.graal.lir.*; import com.oracle.graal.lir.amd64.*; import com.oracle.graal.lir.asm.*; -import com.oracle.graal.phases.*; public class AMD64DeoptimizationStub extends AMD64Code { public static final Descriptor DEOPTIMIZE = new Descriptor("deoptimize", true, void.class); - public static final Descriptor SET_DEOPT_INFO = new Descriptor("setDeoptInfo", true, void.class, Object.class); public final Label label = new Label(); public final LIRFrameState info; public final DeoptimizationAction action; public final DeoptimizationReason reason; - public final Object deoptInfo; - public AMD64DeoptimizationStub(DeoptimizationAction action, DeoptimizationReason reason, LIRFrameState info, Object deoptInfo) { + public AMD64DeoptimizationStub(DeoptimizationAction action, DeoptimizationReason reason, LIRFrameState info) { this.action = action; this.reason = reason; this.info = info; - this.deoptInfo = deoptInfo; } - private static ArrayList<Object> keepAlive = new ArrayList<>(); - @Override public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { Register scratch = tasm.frameMap.registerConfig.getScratchRegister(); - masm.bind(label); - if (GraalOptions.CreateDeoptInfo && deoptInfo != null) { - masm.nop(); - keepAlive.add(deoptInfo.toString()); - AMD64Move.move(tasm, masm, scratch.asValue(), Constant.forObject(deoptInfo)); - AMD64Call.directCall(tasm, masm, tasm.runtime.lookupRuntimeCall(SET_DEOPT_INFO), info); - } - masm.movl(scratch, tasm.runtime.encodeDeoptActionAndReason(action, reason)); AMD64Call.directCall(tasm, masm, tasm.runtime.lookupRuntimeCall(DEOPTIMIZE), info); - AMD64Call.shouldNotReachHere(tasm, masm); } @Override
--- a/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java Tue Mar 12 11:38:24 2013 +0100 +++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java Tue Mar 12 11:38:52 2013 +0100 @@ -34,20 +34,22 @@ import com.oracle.graal.api.code.RuntimeCallTarget.Descriptor; import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.*; +import com.oracle.graal.asm.amd64.AMD64Address.Scale; import com.oracle.graal.asm.amd64.AMD64Assembler.ConditionFlag; import com.oracle.graal.compiler.gen.*; import com.oracle.graal.compiler.target.*; import com.oracle.graal.graph.*; import com.oracle.graal.lir.*; import com.oracle.graal.lir.StandardOp.JumpOp; -import com.oracle.graal.lir.amd64.AMD64Arithmetic.DivOp; +import com.oracle.graal.lir.amd64.*; +import com.oracle.graal.lir.amd64.AMD64Arithmetic.BinaryCommutative; +import com.oracle.graal.lir.amd64.AMD64Arithmetic.BinaryRegConst; +import com.oracle.graal.lir.amd64.AMD64Arithmetic.BinaryRegReg; +import com.oracle.graal.lir.amd64.AMD64Arithmetic.BinaryRegStack; +import com.oracle.graal.lir.amd64.AMD64Arithmetic.BinaryRegStackConst; import com.oracle.graal.lir.amd64.AMD64Arithmetic.DivRemOp; -import com.oracle.graal.lir.amd64.AMD64Arithmetic.Op2Reg; -import com.oracle.graal.lir.amd64.AMD64Arithmetic.Op2Stack; -import com.oracle.graal.lir.amd64.AMD64Arithmetic.ShiftOp; import com.oracle.graal.lir.amd64.AMD64Arithmetic.Unary1Op; import com.oracle.graal.lir.amd64.AMD64Arithmetic.Unary2Op; -import com.oracle.graal.lir.amd64.*; import com.oracle.graal.lir.amd64.AMD64Call.DirectCallOp; import com.oracle.graal.lir.amd64.AMD64Call.IndirectCallOp; import com.oracle.graal.lir.amd64.AMD64Compare.CompareOp; @@ -66,7 +68,6 @@ import com.oracle.graal.lir.amd64.AMD64Move.MoveFromRegOp; import com.oracle.graal.lir.amd64.AMD64Move.MoveToRegOp; import com.oracle.graal.lir.amd64.AMD64Move.NullCheckOp; -import com.oracle.graal.lir.amd64.AMD64Move.SpillMoveOp; import com.oracle.graal.lir.amd64.AMD64Move.StackLeaOp; import com.oracle.graal.lir.amd64.AMD64Move.StoreConstantOp; import com.oracle.graal.lir.amd64.AMD64Move.StoreOp; @@ -93,7 +94,7 @@ @Override public LIRInstruction createMove(Value result, Value input) { - return new SpillMoveOp(result, input); + return AMD64LIRGenerator.createMove(result, input); } } @@ -145,65 +146,77 @@ return result; } - @Override - public void emitMove(Value dst, Value src) { + private static AMD64LIRInstruction createMove(Value dst, Value src) { if (isRegister(src) || isStackSlot(dst)) { - append(new MoveFromRegOp(dst, src)); + return new MoveFromRegOp(dst, src); } else { - append(new MoveToRegOp(dst, src)); + return new MoveToRegOp(dst, src); } } - private AMD64Address prepareAddress(Kind kind, Value base, int displacement, Value index, int scale) { - Value baseRegister = base; + @Override + public void emitMove(Value dst, Value src) { + append(createMove(dst, src)); + } + + private AMD64AddressValue prepareAddress(Kind kind, Value base, int displacement, Value index, int scale) { + AllocatableValue baseRegister; int finalDisp = displacement; if (isConstant(base)) { if (asConstant(base).isNull()) { - baseRegister = Value.ILLEGAL; + baseRegister = AllocatableValue.UNUSED; } else if (asConstant(base).getKind() != Kind.Object) { long newDisplacement = displacement + asConstant(base).asLong(); if (NumUtil.isInt(newDisplacement)) { assert !runtime.needsDataPatch(asConstant(base)); finalDisp = (int) newDisplacement; - baseRegister = Value.ILLEGAL; + baseRegister = AllocatableValue.UNUSED; } else { - Value newBase = newVariable(Kind.Long); + Variable newBase = newVariable(Kind.Long); emitMove(newBase, base); baseRegister = newBase; } + } else { + baseRegister = load(base); } + } else if (base == Value.ILLEGAL) { + baseRegister = AllocatableValue.UNUSED; + } else { + baseRegister = asAllocatable(base); } - Value indexRegister = index; - AMD64Address.Scale scaleEnum; - if (index != Value.ILLEGAL && scale > 0) { - scaleEnum = AMD64Address.Scale.fromInt(scale); + AllocatableValue indexRegister; + Scale scaleEnum; + if (index != Value.ILLEGAL && scale != 0) { + scaleEnum = Scale.fromInt(scale); if (isConstant(index)) { long newDisplacement = finalDisp + asConstant(index).asLong() * scale; // only use the constant index if the resulting displacement fits into a 32 bit // offset if (NumUtil.isInt(newDisplacement)) { finalDisp = (int) newDisplacement; - indexRegister = Value.ILLEGAL; + indexRegister = AllocatableValue.UNUSED; } else { // create a temporary variable for the index, the pointer load cannot handle a // constant index - Value newIndex = newVariable(Kind.Long); + Variable newIndex = newVariable(Kind.Long); emitMove(newIndex, index); indexRegister = newIndex; } + } else { + indexRegister = asAllocatable(index); } } else { - indexRegister = Value.ILLEGAL; - scaleEnum = AMD64Address.Scale.Times1; + indexRegister = AllocatableValue.UNUSED; + scaleEnum = Scale.Times1; } - return new AMD64Address(kind, baseRegister, indexRegister, scaleEnum, finalDisp); + return new AMD64AddressValue(kind, baseRegister, indexRegister, scaleEnum, finalDisp); } @Override public Variable emitLoad(Kind kind, Value base, int displacement, Value index, int scale, boolean canTrap) { - AMD64Address loadAddress = prepareAddress(kind, base, displacement, index, scale); + AMD64AddressValue loadAddress = prepareAddress(kind, base, displacement, index, scale); Variable result = newVariable(loadAddress.getKind()); append(new LoadOp(result, loadAddress, canTrap ? state() : null)); return result; @@ -211,7 +224,7 @@ @Override public void emitStore(Kind kind, Value base, int displacement, Value index, int scale, Value inputVal, boolean canTrap) { - AMD64Address storeAddress = prepareAddress(kind, base, displacement, index, scale); + AMD64AddressValue storeAddress = prepareAddress(kind, base, displacement, index, scale); LIRFrameState state = canTrap ? state() : null; if (isConstant(inputVal)) { @@ -229,7 +242,7 @@ @Override public Variable emitLea(Value base, int displacement, Value index, int scale) { Variable result = newVariable(target().wordKind); - AMD64Address address = prepareAddress(result.getKind(), base, displacement, index, scale); + AMD64AddressValue address = prepareAddress(result.getKind(), base, displacement, index, scale); append(new LeaOp(result, address)); return result; } @@ -266,6 +279,11 @@ } @Override + public void emitOverflowCheckBranch(LabelRef destination, LIRFrameState info, boolean negated) { + append(new BranchOp(negated ? ConditionFlag.NoOverflow : ConditionFlag.Overflow, destination, info)); + } + + @Override public void emitIntegerTestBranch(Value left, Value right, boolean negated, LabelRef label, LIRFrameState info) { emitIntegerTest(left, right); append(new BranchOp(negated ? Condition.NE : Condition.EQ, label, info)); @@ -365,32 +383,10 @@ append(new Unary1Op(LNEG, result, input)); break; case Float: - append(new Op2Reg(FXOR, result, input, Constant.forFloat(Float.intBitsToFloat(0x80000000)))); + append(new BinaryRegConst(FXOR, result, input, Constant.forFloat(Float.intBitsToFloat(0x80000000)))); break; case Double: - append(new Op2Reg(DXOR, result, input, Constant.forDouble(Double.longBitsToDouble(0x8000000000000000L)))); - break; - default: - throw GraalInternalError.shouldNotReachHere(); - } - return result; - } - - @Override - public Variable emitAdd(Value a, Value b) { - Variable result = newVariable(a.getKind()); - switch (a.getKind()) { - case Int: - append(new Op2Stack(IADD, result, a, loadNonConst(b))); - break; - case Long: - append(new Op2Stack(LADD, result, a, loadNonConst(b))); - break; - case Float: - append(new Op2Stack(FADD, result, a, loadNonConst(b))); - break; - case Double: - append(new Op2Stack(DADD, result, a, loadNonConst(b))); + append(new BinaryRegConst(DXOR, result, input, Constant.forDouble(Double.longBitsToDouble(0x8000000000000000L)))); break; default: throw GraalInternalError.shouldNotReachHere(); @@ -398,48 +394,104 @@ return result; } - @Override - public Variable emitSub(Value a, Value b) { - Variable result = newVariable(a.getKind()); - switch (a.getKind()) { - case Int: - append(new Op2Stack(ISUB, result, a, loadNonConst(b))); + private Variable emitBinary(AMD64Arithmetic op, boolean commutative, Value a, Value b) { + if (isConstant(b)) { + return emitBinaryConst(op, commutative, asAllocatable(a), asConstant(b)); + } else if (commutative && isConstant(a)) { + return emitBinaryConst(op, commutative, asAllocatable(b), asConstant(a)); + } else { + return emitBinaryVar(op, commutative, asAllocatable(a), asAllocatable(b)); + } + } + + private Variable emitBinaryConst(AMD64Arithmetic op, boolean commutative, AllocatableValue a, Constant b) { + switch (op) { + case IADD: + case LADD: + case ISUB: + case LSUB: + case IAND: + case LAND: + case IOR: + case LOR: + case IXOR: + case LXOR: + if (NumUtil.isInt(b.asLong())) { + Variable result = newVariable(a.getKind()); + append(new BinaryRegConst(op, result, a, b)); + return result; + } break; - case Long: - append(new Op2Stack(LSUB, result, a, loadNonConst(b))); - break; - case Float: - append(new Op2Stack(FSUB, result, a, loadNonConst(b))); + + case IMUL: + case LMUL: + if (NumUtil.isInt(b.asLong())) { + Variable result = newVariable(a.getKind()); + append(new BinaryRegStackConst(op, result, a, b)); + return result; + } break; - case Double: - append(new Op2Stack(DSUB, result, a, loadNonConst(b))); - break; - default: - throw GraalInternalError.shouldNotReachHere(); + } + + return emitBinaryVar(op, commutative, a, asAllocatable(b)); + } + + private Variable emitBinaryVar(AMD64Arithmetic op, boolean commutative, AllocatableValue a, AllocatableValue b) { + Variable result = newVariable(a.getKind()); + if (commutative) { + append(new BinaryCommutative(op, result, a, b)); + } else { + append(new BinaryRegStack(op, result, a, b)); } return result; } @Override - public Variable emitMul(Value a, Value b) { - Variable result = newVariable(a.getKind()); + public Variable emitAdd(Value a, Value b) { switch (a.getKind()) { case Int: - append(new Op2Reg(IMUL, result, a, loadNonConst(b))); - break; + return emitBinary(IADD, true, a, b); case Long: - append(new Op2Reg(LMUL, result, a, loadNonConst(b))); - break; + return emitBinary(LADD, true, a, b); case Float: - append(new Op2Stack(FMUL, result, a, loadNonConst(b))); - break; + return emitBinary(FADD, true, a, b); case Double: - append(new Op2Stack(DMUL, result, a, loadNonConst(b))); - break; + return emitBinary(DADD, true, a, b); default: throw GraalInternalError.shouldNotReachHere(); } - return result; + } + + @Override + public Variable emitSub(Value a, Value b) { + switch (a.getKind()) { + case Int: + return emitBinary(ISUB, false, a, b); + case Long: + return emitBinary(LSUB, false, a, b); + case Float: + return emitBinary(FSUB, false, a, b); + case Double: + return emitBinary(DSUB, false, a, b); + default: + throw GraalInternalError.shouldNotReachHere(); + } + } + + @Override + public Variable emitMul(Value a, Value b) { + switch (a.getKind()) { + case Int: + return emitBinary(IMUL, true, a, b); + case Long: + return emitBinary(LMUL, true, a, b); + case Float: + return emitBinary(FMUL, true, a, b); + case Double: + return emitBinary(DMUL, true, a, b); + default: + throw GraalInternalError.shouldNotReachHere(); + } } @Override @@ -469,15 +521,19 @@ return false; } + private void emitDivRem(AMD64Arithmetic op, Value a, Value b) { + AllocatableValue rax = AMD64.rax.asValue(a.getKind()); + emitMove(rax, a); + append(new DivRemOp(op, rax, asAllocatable(b), state())); + } + public Value[] emitIntegerDivRem(Value a, Value b) { switch (a.getKind()) { case Int: - emitMove(RAX_I, a); - append(new DivRemOp(IDIVREM, RAX_I, load(b), state())); + emitDivRem(IDIVREM, a, b); return new Value[]{emitMove(RAX_I), emitMove(RDX_I)}; case Long: - emitMove(RAX_L, a); - append(new DivRemOp(LDIVREM, RAX_L, load(b), state())); + emitDivRem(LDIVREM, a, b); return new Value[]{emitMove(RAX_L), emitMove(RDX_L)}; default: throw GraalInternalError.shouldNotReachHere(); @@ -488,21 +544,19 @@ public Value emitDiv(Value a, Value b) { switch (a.getKind()) { case Int: - emitMove(RAX_I, a); - append(new DivOp(IDIV, RAX_I, RAX_I, load(b), state())); + emitDivRem(IDIV, a, b); return emitMove(RAX_I); case Long: - emitMove(RAX_L, a); - append(new DivOp(LDIV, RAX_L, RAX_L, load(b), state())); + emitDivRem(LDIV, a, b); return emitMove(RAX_L); case Float: { Variable result = newVariable(a.getKind()); - append(new Op2Stack(FDIV, result, a, loadNonConst(b))); + append(new BinaryRegStack(FDIV, result, asAllocatable(a), asAllocatable(b))); return result; } case Double: { Variable result = newVariable(a.getKind()); - append(new Op2Stack(DDIV, result, a, loadNonConst(b))); + append(new BinaryRegStack(DDIV, result, asAllocatable(a), asAllocatable(b))); return result; } default: @@ -514,12 +568,10 @@ public Value emitRem(Value a, Value b) { switch (a.getKind()) { case Int: - emitMove(RAX_I, a); - append(new DivOp(IREM, RDX_I, RAX_I, load(b), state())); + emitDivRem(IREM, a, b); return emitMove(RDX_I); case Long: - emitMove(RAX_L, a); - append(new DivOp(LREM, RDX_L, RAX_L, load(b), state())); + emitDivRem(LREM, a, b); return emitMove(RDX_L); case Float: { RuntimeCallTarget stub = runtime.lookupRuntimeCall(ARITHMETIC_FREM); @@ -538,12 +590,10 @@ public Variable emitUDiv(Value a, Value b) { switch (a.getKind()) { case Int: - emitMove(RAX_I, a); - append(new DivOp(IUDIV, RAX_I, RAX_I, load(b), state())); + emitDivRem(IUDIV, a, b); return emitMove(RAX_I); case Long: - emitMove(RAX_L, a); - append(new DivOp(LUDIV, RAX_L, RAX_L, load(b), state())); + emitDivRem(LUDIV, a, b); return emitMove(RAX_L); default: throw GraalInternalError.shouldNotReachHere(); @@ -554,12 +604,10 @@ public Variable emitURem(Value a, Value b) { switch (a.getKind()) { case Int: - emitMove(RAX_I, a); - append(new DivOp(IUREM, RDX_I, RAX_I, load(b), state())); + emitDivRem(IUREM, a, b); return emitMove(RDX_I); case Long: - emitMove(RAX_L, a); - append(new DivOp(LUREM, RDX_L, RAX_L, load(b), state())); + emitDivRem(LUREM, a, b); return emitMove(RDX_L); default: throw GraalInternalError.shouldNotReachHere(); @@ -568,107 +616,86 @@ @Override public Variable emitAnd(Value a, Value b) { - Variable result = newVariable(a.getKind()); switch (a.getKind()) { case Int: - append(new Op2Stack(IAND, result, a, loadNonConst(b))); - break; + return emitBinary(IAND, true, a, b); case Long: - append(new Op2Stack(LAND, result, a, loadNonConst(b))); - break; + return emitBinary(LAND, true, a, b); default: throw GraalInternalError.shouldNotReachHere(); } - return result; } @Override public Variable emitOr(Value a, Value b) { - Variable result = newVariable(a.getKind()); switch (a.getKind()) { case Int: - append(new Op2Stack(IOR, result, a, loadNonConst(b))); - break; + return emitBinary(IOR, true, a, b); case Long: - append(new Op2Stack(LOR, result, a, loadNonConst(b))); - break; + return emitBinary(LOR, true, a, b); default: throw GraalInternalError.shouldNotReachHere(); } - return result; } @Override public Variable emitXor(Value a, Value b) { - Variable result = newVariable(a.getKind()); switch (a.getKind()) { case Int: - append(new Op2Stack(IXOR, result, a, loadNonConst(b))); - break; + return emitBinary(IXOR, true, a, b); case Long: - append(new Op2Stack(LXOR, result, a, loadNonConst(b))); - break; + return emitBinary(LXOR, true, a, b); default: throw GraalInternalError.shouldNotReachHere(); } + } + + private Variable emitShift(AMD64Arithmetic op, Value a, Value b) { + Variable result = newVariable(a.getKind()); + AllocatableValue input = asAllocatable(a); + if (isConstant(b)) { + append(new BinaryRegConst(op, result, input, asConstant(b))); + } else { + emitMove(RCX_I, b); + append(new BinaryRegReg(op, result, input, RCX_I)); + } return result; } @Override public Variable emitShl(Value a, Value b) { - Variable result = newVariable(a.getKind()); switch (a.getKind()) { case Int: - append(new ShiftOp(ISHL, result, a, loadShiftCount(b))); - break; + return emitShift(ISHL, a, b); case Long: - append(new ShiftOp(LSHL, result, a, loadShiftCount(b))); - break; + return emitShift(LSHL, a, b); default: - GraalInternalError.shouldNotReachHere(); + throw GraalInternalError.shouldNotReachHere(); } - return result; } @Override public Variable emitShr(Value a, Value b) { - Variable result = newVariable(a.getKind()); switch (a.getKind()) { case Int: - append(new ShiftOp(ISHR, result, a, loadShiftCount(b))); - break; + return emitShift(ISHR, a, b); case Long: - append(new ShiftOp(LSHR, result, a, loadShiftCount(b))); - break; + return emitShift(LSHR, a, b); default: - GraalInternalError.shouldNotReachHere(); + throw GraalInternalError.shouldNotReachHere(); } - return result; } @Override public Variable emitUShr(Value a, Value b) { - Variable result = newVariable(a.getKind()); switch (a.getKind()) { case Int: - append(new ShiftOp(IUSHR, result, a, loadShiftCount(b))); - break; + return emitShift(IUSHR, a, b); case Long: - append(new ShiftOp(LUSHR, result, a, loadShiftCount(b))); - break; + return emitShift(LUSHR, a, b); default: - GraalInternalError.shouldNotReachHere(); + throw GraalInternalError.shouldNotReachHere(); } - return result; - } - - private Value loadShiftCount(Value value) { - if (isConstant(value)) { - return value; - } - // Non-constant shift count must be in RCX - emitMove(RCX_I, value); - return RCX_I; } @Override @@ -746,20 +773,13 @@ } @Override - public void emitDeoptimizeOnOverflow(DeoptimizationAction action, DeoptimizationReason reason, Object deoptInfo) { - LIRFrameState info = state(); - LabelRef stubEntry = createDeoptStub(action, reason, info, deoptInfo); + public void emitDeoptimizeOnOverflow(DeoptimizationAction action, DeoptimizationReason reason) { + LIRFrameState info = state(reason); + LabelRef stubEntry = createDeoptStub(action, reason, info); append(new BranchOp(ConditionFlag.Overflow, stubEntry, info)); } @Override - public void emitDeoptimize(DeoptimizationAction action, DeoptimizationReason reason, Object deoptInfo) { - LIRFrameState info = state(); - LabelRef stubEntry = createDeoptStub(action, reason, info, deoptInfo); - append(new JumpOp(stubEntry, info)); - } - - @Override public void emitMembar(int barriers) { int necessaryBarriers = target.arch.requiredBarriers(barriers); if (target.isMP && necessaryBarriers != 0) { @@ -815,7 +835,7 @@ @Override public void emitMathAbs(Variable result, Variable input) { - append(new Op2Reg(DAND, result, input, Constant.forDouble(Double.longBitsToDouble(0x7FFFFFFFFFFFFFFFL)))); + append(new BinaryRegConst(DAND, result, input, Constant.forDouble(Double.longBitsToDouble(0x7FFFFFFFFFFFFFFFL)))); } @Override @@ -879,15 +899,23 @@ } @Override - protected LabelRef createDeoptStub(DeoptimizationAction action, DeoptimizationReason reason, LIRFrameState info, Object deoptInfo) { + protected LabelRef createDeoptStub(DeoptimizationAction action, DeoptimizationReason reason, LIRFrameState info) { assert info.topFrame.getBCI() >= 0 : "invalid bci for deopt framestate"; - AMD64DeoptimizationStub stub = new AMD64DeoptimizationStub(action, reason, info, deoptInfo); + AMD64DeoptimizationStub stub = new AMD64DeoptimizationStub(action, reason, info); lir.stubs.add(stub); return LabelRef.forLabel(stub.label); } @Override - protected void emitNullCheckGuard(ValueNode object) { + public void emitGuardCheck(LogicNode comp, DeoptimizationReason deoptReason, DeoptimizationAction action, boolean negated) { + if (comp instanceof IsNullNode && negated) { + emitNullCheckGuard(((IsNullNode) comp).object()); + } else { + super.emitGuardCheck(comp, deoptReason, action, negated); + } + } + + private void emitNullCheckGuard(ValueNode object) { Variable value = load(operand(object)); LIRFrameState info = state(); append(new NullCheckOp(value, info)); @@ -901,15 +929,15 @@ Value expected = loadNonConst(operand(node.expected())); Variable newValue = load(operand(node.newValue())); - AMD64Address address; + AMD64AddressValue address; int displacement = node.displacement(); Value index = operand(node.offset()); if (isConstant(index) && NumUtil.isInt(asConstant(index).asLong() + displacement)) { assert !runtime.needsDataPatch(asConstant(index)); displacement += (int) asConstant(index).asLong(); - address = new AMD64Address(kind, load(operand(node.object())), displacement); + address = new AMD64AddressValue(kind, load(operand(node.object())), displacement); } else { - address = new AMD64Address(kind, load(operand(node.object())), load(index), AMD64Address.Scale.Times1, displacement); + address = new AMD64AddressValue(kind, load(operand(node.object())), load(index), Scale.Times1, displacement); } RegisterValue rax = AMD64.rax.asValue(kind);
--- a/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/BasicPTXTest.java Tue Mar 12 11:38:24 2013 +0100 +++ b/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/BasicPTXTest.java Tue Mar 12 11:38:52 2013 +0100 @@ -25,6 +25,7 @@ import org.junit.*; import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; import com.oracle.graal.api.runtime.*; import com.oracle.graal.compiler.*; import com.oracle.graal.compiler.ptx.*; @@ -32,6 +33,7 @@ import com.oracle.graal.debug.*; import com.oracle.graal.java.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.type.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.PhasePlan.*; import com.oracle.graal.ptx.*; @@ -42,13 +44,21 @@ public class BasicPTXTest extends GraalCompilerTest { @Test - public void test1() { - test("test1Snippet"); + public void testAdd() { + test("testAddSnippet"); + } + + public static int testAddSnippet(int a) { + return a + 1; } - @SuppressWarnings("all") - public static int test1Snippet(int a) { - return a + 1; + @Test + public void testArray() { + test("testArraySnippet"); + } + + public static int testArraySnippet(int[] array) { + return array[0]; } private void test(String snippet) { @@ -59,7 +69,23 @@ PhasePlan phasePlan = new PhasePlan(); GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getDefault(), OptimisticOptimizations.NONE); phasePlan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase); - CompilationResult result = GraalCompiler.compileMethod(runtime, ptxBackend, target, graph.method(), graph, null, phasePlan, OptimisticOptimizations.NONE); + phasePlan.addPhase(PhasePosition.AFTER_PARSING, new PTXPhase()); + new PTXPhase().apply(graph); + CompilationResult result = GraalCompiler.compileMethod(runtime, ptxBackend, target, graph.method(), graph, null, phasePlan, OptimisticOptimizations.NONE, new SpeculationLog()); System.out.println("result=" + result); } + + private static class PTXPhase extends Phase { + + @Override + protected void run(StructuredGraph graph) { + System.out.println("PTX phase"); + for (LocalNode local : graph.getNodes(LocalNode.class)) { + if (local.kind() == Kind.Object) { + local.setStamp(StampFactory.declaredNonNull(local.objectStamp().type())); + } + } + } + + } }
--- a/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXBackend.java Tue Mar 12 11:38:24 2013 +0100 +++ b/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXBackend.java Tue Mar 12 11:38:52 2013 +0100 @@ -74,7 +74,7 @@ AbstractAssembler masm = new PTXAssembler(target, frameMap.registerConfig); HotSpotFrameContext frameContext = omitFrame ? null : new HotSpotFrameContext(); - TargetMethodAssembler tasm = new TargetMethodAssembler(target, runtime(), frameMap, masm, frameContext, lir.stubs); + TargetMethodAssembler tasm = new TargetMethodAssembler(target, runtime(), frameMap, masm, frameContext); tasm.setFrameSize(frameMap.frameSize()); tasm.compilationResult.setCustomStackAreaOffset(frameMap.offsetToCustomArea()); return tasm;
--- a/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXDeoptimizationStub.java Tue Mar 12 11:38:24 2013 +0100 +++ b/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXDeoptimizationStub.java Tue Mar 12 11:38:52 2013 +0100 @@ -40,13 +40,11 @@ public final LIRFrameState info; public final DeoptimizationAction action; public final DeoptimizationReason reason; - public final Object deoptInfo; - public PTXDeoptimizationStub(DeoptimizationAction action, DeoptimizationReason reason, LIRFrameState info, Object deoptInfo) { + public PTXDeoptimizationStub(DeoptimizationAction action, DeoptimizationReason reason, LIRFrameState info) { this.action = action; this.reason = reason; this.info = info; - this.deoptInfo = deoptInfo; } @Override
--- a/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXLIRGenerator.java Tue Mar 12 11:38:24 2013 +0100 +++ b/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXLIRGenerator.java Tue Mar 12 11:38:52 2013 +0100 @@ -36,11 +36,11 @@ import com.oracle.graal.graph.*; import com.oracle.graal.lir.*; import com.oracle.graal.lir.StandardOp.JumpOp; +import com.oracle.graal.lir.ptx.*; import com.oracle.graal.lir.ptx.PTXArithmetic.Op1Stack; import com.oracle.graal.lir.ptx.PTXArithmetic.Op2Reg; import com.oracle.graal.lir.ptx.PTXArithmetic.Op2Stack; import com.oracle.graal.lir.ptx.PTXArithmetic.ShiftOp; -import com.oracle.graal.lir.ptx.*; import com.oracle.graal.lir.ptx.PTXCompare.CompareOp; import com.oracle.graal.lir.ptx.PTXControlFlow.BranchOp; import com.oracle.graal.lir.ptx.PTXControlFlow.ReturnOp; @@ -51,7 +51,6 @@ import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.java.*; -import com.oracle.graal.ptx.*; /** * This class implements the PTX specific portion of the LIR generator. @@ -114,40 +113,49 @@ } } - private PTXAddress prepareAddress(Kind kind, Value base, int displacement, Value index, int scale) { - Value baseRegister = base; + private PTXAddressValue prepareAddress(Kind kind, Value base, int displacement, Value index, int scale) { + AllocatableValue baseRegister; long finalDisp = displacement; if (isConstant(base)) { if (asConstant(base).isNull()) { - baseRegister = Value.ILLEGAL; + baseRegister = AllocatableValue.UNUSED; } else if (asConstant(base).getKind() != Kind.Object) { finalDisp += asConstant(base).asLong(); - baseRegister = Value.ILLEGAL; + baseRegister = AllocatableValue.UNUSED; + } else { + baseRegister = load(base); } + } else if (base == Value.ILLEGAL) { + baseRegister = AllocatableValue.UNUSED; + } else { + baseRegister = asAllocatable(base); } if (index != Value.ILLEGAL) { if (isConstant(index)) { finalDisp += asConstant(index).asLong() * scale; } else { - Value indexRegister = index; + Value indexRegister; if (scale != 1) { indexRegister = emitMul(index, Constant.forInt(scale)); + } else { + indexRegister = index; } - if (baseRegister == Value.ILLEGAL) { - baseRegister = indexRegister; + + if (baseRegister == AllocatableValue.UNUSED) { + baseRegister = asAllocatable(indexRegister); } else { baseRegister = emitAdd(baseRegister, indexRegister); } } } - return new PTXAddress(kind, baseRegister, finalDisp); + return new PTXAddressValue(kind, baseRegister, finalDisp); } @Override public Variable emitLoad(Kind kind, Value base, int displacement, Value index, int scale, boolean canTrap) { - PTXAddress loadAddress = prepareAddress(kind, base, displacement, index, scale); + PTXAddressValue loadAddress = prepareAddress(kind, base, displacement, index, scale); Variable result = newVariable(loadAddress.getKind()); append(new LoadOp(result, loadAddress, canTrap ? state() : null)); return result; @@ -155,7 +163,7 @@ @Override public void emitStore(Kind kind, Value base, int displacement, Value index, int scale, Value inputVal, boolean canTrap) { - PTXAddress storeAddress = prepareAddress(kind, base, displacement, index, scale); + PTXAddressValue storeAddress = prepareAddress(kind, base, displacement, index, scale); Variable input = load(inputVal); append(new StoreOp(storeAddress, input, canTrap ? state() : null)); } @@ -192,6 +200,11 @@ } @Override + public void emitOverflowCheckBranch(LabelRef label, LIRFrameState info, boolean negated) { + throw new InternalError("NYI"); + } + + @Override public void emitIntegerTestBranch(Value left, Value right, boolean negated, LabelRef label, LIRFrameState info) { throw new InternalError("NYI"); } @@ -336,13 +349,13 @@ } @Override - public void emitDeoptimizeOnOverflow(DeoptimizationAction action, DeoptimizationReason reason, Object deoptInfo) { + public void emitDeoptimizeOnOverflow(DeoptimizationAction action, DeoptimizationReason reason) { throw new InternalError("NYI"); } @Override - public void emitDeoptimize(DeoptimizationAction action, DeoptimizationReason reason, Object deoptInfo) { - throw new InternalError("NYI"); + public void emitDeoptimize(DeoptimizationAction action, DeoptimizationReason reason) { + append(new ReturnOp(Value.ILLEGAL)); } @Override @@ -440,19 +453,14 @@ } @Override - protected LabelRef createDeoptStub(DeoptimizationAction action, DeoptimizationReason reason, LIRFrameState info, Object deoptInfo) { + protected LabelRef createDeoptStub(DeoptimizationAction action, DeoptimizationReason reason, LIRFrameState info) { assert info.topFrame.getBCI() >= 0 : "invalid bci for deopt framestate"; - PTXDeoptimizationStub stub = new PTXDeoptimizationStub(action, reason, info, deoptInfo); + PTXDeoptimizationStub stub = new PTXDeoptimizationStub(action, reason, info); lir.stubs.add(stub); return LabelRef.forLabel(stub.label); } @Override - protected void emitNullCheckGuard(ValueNode object) { - throw new InternalError("NYI"); - } - - @Override public void visitCompareAndSwap(CompareAndSwapNode node) { throw new InternalError("NYI"); } @@ -471,4 +479,10 @@ public void visitSafepointNode(SafepointNode i) { throw new InternalError("NYI"); } + + @Override + public void emitUnwind(Value operand) { + // TODO Auto-generated method stub + + } }
--- a/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java Tue Mar 12 11:38:24 2013 +0100 +++ b/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java Tue Mar 12 11:38:52 2013 +0100 @@ -62,12 +62,6 @@ } @Override - protected void emitNullCheckGuard(ValueNode object) { - // SPARC: Auto-generated method stub - - } - - @Override public void emitJump(LabelRef label, LIRFrameState info) { @SuppressWarnings("unused") SPARCLIRInstruction instruction = null; @@ -82,6 +76,12 @@ } @Override + public void emitOverflowCheckBranch(LabelRef label, LIRFrameState info, boolean negated) { + // SPARC: Auto-generated method stub + + } + + @Override public void emitIntegerTestBranch(Value left, Value right, boolean negated, LabelRef label, LIRFrameState info) { // SPARC: Auto-generated method stub @@ -118,7 +118,7 @@ } @Override - protected LabelRef createDeoptStub(DeoptimizationAction action, DeoptimizationReason reason, LIRFrameState info, Object deoptInfo) { + protected LabelRef createDeoptStub(DeoptimizationAction action, DeoptimizationReason reason, LIRFrameState info) { // SPARC: Auto-generated method stub return null; } @@ -340,13 +340,13 @@ } @Override - public void emitDeoptimizeOnOverflow(DeoptimizationAction action, DeoptimizationReason reason, Object deoptInfo) { + public void emitDeoptimizeOnOverflow(DeoptimizationAction action, DeoptimizationReason reason) { // SPARC: Auto-generated method stub } @Override - public void emitDeoptimize(DeoptimizationAction action, DeoptimizationReason reason, Object deoptInfo) { + public void emitDeoptimize(DeoptimizationAction action, DeoptimizationReason reason) { // SPARC: Auto-generated method stub } @@ -374,4 +374,10 @@ // SPARC: Auto-generated method stub } + + @Override + public void emitUnwind(Value operand) { + // TODO Auto-generated method stub + + } }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java Tue Mar 12 11:38:24 2013 +0100 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java Tue Mar 12 11:38:52 2013 +0100 @@ -68,13 +68,11 @@ public abstract class GraalCompilerTest extends GraalTest { protected final GraalCodeCacheProvider runtime; - protected final GraalCompiler graalCompiler; protected final Backend backend; public GraalCompilerTest() { DebugEnvironment.initialize(System.out); this.runtime = Graal.getRequiredCapability(GraalCodeCacheProvider.class); - this.graalCompiler = Graal.getRequiredCapability(GraalCompiler.class); this.backend = Graal.getRequiredCapability(Backend.class); } @@ -350,7 +348,7 @@ final int id = compilationId++; - InstalledCode installedCode = Debug.scope("Compiling", new DebugDumpScope(String.valueOf(id), true), new Callable<InstalledCode>() { + InstalledCode installedCode = Debug.scope("Compiling", new Object[]{runtime, new DebugDumpScope(String.valueOf(id), true)}, new Callable<InstalledCode>() { public InstalledCode call() throws Exception { final boolean printCompilation = GraalOptions.PrintCompilation && !TTY.isSuppressed(); @@ -362,7 +360,8 @@ GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getDefault(), OptimisticOptimizations.ALL); phasePlan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase); editPhasePlan(method, graph, phasePlan); - CompilationResult compResult = GraalCompiler.compileMethod(runtime(), backend, runtime().getTarget(), method, graph, null, phasePlan, OptimisticOptimizations.ALL); + CompilationResult compResult = GraalCompiler.compileMethod(runtime(), backend, runtime().getTarget(), method, graph, null, phasePlan, OptimisticOptimizations.ALL, + new SpeculationLog()); if (printCompilation) { TTY.println(String.format("@%-6d Graal %-70s %-45s %-50s | %4dms %5dB", id, "", "", "", System.currentTimeMillis() - start, compResult.getTargetCodeSize())); } @@ -377,8 +376,7 @@ } protected InstalledCode addMethod(final ResolvedJavaMethod method, final CompilationResult compResult) { - assert graalCompiler != null; - return Debug.scope("CodeInstall", new Object[]{graalCompiler, method}, new Callable<InstalledCode>() { + return Debug.scope("CodeInstall", new Object[]{runtime, method}, new Callable<InstalledCode>() { @Override public InstalledCode call() throws Exception {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/backend/AllocatorTest.java Tue Mar 12 11:38:52 2013 +0100 @@ -0,0 +1,131 @@ +/* + * 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.graal.compiler.test.backend; + +import java.util.*; +import java.util.concurrent.*; + +import org.junit.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.*; +import com.oracle.graal.compiler.test.*; +import com.oracle.graal.debug.*; +import com.oracle.graal.lir.*; +import com.oracle.graal.lir.LIRInstruction.ValueProcedure; +import com.oracle.graal.lir.StandardOp.MoveOp; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.cfg.*; +import com.oracle.graal.phases.*; + +public class AllocatorTest extends GraalCompilerTest { + + protected void test(String snippet, final int expectedRegisters, final int expectedRegRegMoves, final int expectedSpillMoves) { + final StructuredGraph graph = parse(snippet); + Debug.scope("AllocatorTest", new Object[]{graph, graph.method(), runtime}, new Runnable() { + + @Override + public void run() { + final RegisterStats stats = getRegisterStats(graph); + + Debug.scope("Assertions", stats.lir, new Runnable() { + + @Override + public void run() { + Assert.assertEquals("register count", expectedRegisters, stats.registers.size()); + Assert.assertEquals("reg-reg moves", expectedRegRegMoves, stats.regRegMoves); + Assert.assertEquals("spill moves", expectedSpillMoves, stats.spillMoves); + } + }); + } + }); + } + + private class RegisterStats { + + public final LIR lir; + public HashSet<Register> registers = new HashSet<>(); + public int regRegMoves; + public int spillMoves; + + public RegisterStats(LIR lir) { + this.lir = lir; + + for (Block block : lir.codeEmittingOrder()) { + for (LIRInstruction instr : lir.lir(block)) { + collectStats(instr); + } + } + } + + private void collectStats(final LIRInstruction instr) { + instr.forEachOutput(new ValueProcedure() { + + @Override + public Value doValue(Value value) { + if (ValueUtil.isRegister(value)) { + final Register reg = ValueUtil.asRegister(value); + registers.add(reg); + } + return value; + } + }); + + if (instr instanceof MoveOp) { + MoveOp move = (MoveOp) instr; + Value def = move.getResult(); + Value use = move.getInput(); + if (ValueUtil.isRegister(def)) { + if (ValueUtil.isRegister(use) && ValueUtil.asRegister(def) != ValueUtil.asRegister(use)) { + regRegMoves++; + } + } else if (ValueUtil.isStackSlot(def)) { + spillMoves++; + } + } + } + } + + private RegisterStats getRegisterStats(final StructuredGraph graph) { + final PhasePlan phasePlan = getDefaultPhasePlan(); + final Assumptions assumptions = new Assumptions(GraalOptions.OptAssumptions); + + final LIR lir = Debug.scope("FrontEnd", new Callable<LIR>() { + + @Override + public LIR call() { + return GraalCompiler.emitHIR(runtime, backend.target, graph, assumptions, null, phasePlan, OptimisticOptimizations.NONE, new SpeculationLog()); + } + }); + + return Debug.scope("BackEnd", lir, new Callable<RegisterStats>() { + + @Override + public RegisterStats call() { + GraalCompiler.emitLIR(backend, backend.target, lir, graph, graph.method()); + return new RegisterStats(lir); + } + }); + } +}
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java Tue Mar 12 11:38:24 2013 +0100 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java Tue Mar 12 11:38:52 2013 +0100 @@ -48,17 +48,17 @@ public class GraalCompiler { public static CompilationResult compileMethod(final GraalCodeCacheProvider runtime, final Backend backend, final TargetDescription target, final ResolvedJavaMethod method, - final StructuredGraph graph, final GraphCache cache, final PhasePlan plan, final OptimisticOptimizations optimisticOpts) { + final StructuredGraph graph, final GraphCache cache, final PhasePlan plan, final OptimisticOptimizations optimisticOpts, final SpeculationLog speculationLog) { assert (method.getModifiers() & Modifier.NATIVE) == 0 : "compiling native methods is not supported"; - return Debug.scope("GraalCompiler", new Object[]{graph, method}, new Callable<CompilationResult>() { + return Debug.scope("GraalCompiler", new Object[]{graph, method, runtime}, new Callable<CompilationResult>() { public CompilationResult call() { final Assumptions assumptions = new Assumptions(GraalOptions.OptAssumptions); final LIR lir = Debug.scope("FrontEnd", new Callable<LIR>() { public LIR call() { - return emitHIR(runtime, target, graph, assumptions, cache, plan, optimisticOpts); + return emitHIR(runtime, target, graph, assumptions, cache, plan, optimisticOpts, speculationLog); } }); final FrameMap frameMap = Debug.scope("BackEnd", lir, new Callable<FrameMap>() { @@ -96,7 +96,11 @@ * @param target */ public static LIR emitHIR(GraalCodeCacheProvider runtime, TargetDescription target, StructuredGraph graph, Assumptions assumptions, GraphCache cache, PhasePlan plan, - OptimisticOptimizations optimisticOpts) { + OptimisticOptimizations optimisticOpts, final SpeculationLog speculationLog) { + + if (speculationLog != null) { + speculationLog.snapshot(); + } if (graph.start().next() == null) { plan.runPhases(PhasePosition.AFTER_PARSING, graph); @@ -193,10 +197,10 @@ plan.runPhases(PhasePosition.LOW_LEVEL, graph); + new GuardLoweringPhase().apply(graph); + // Add safepoints to loops - if (GraalOptions.GenLoopSafepoints) { - new LoopSafepointInsertionPhase().apply(graph); - } + new SafepointInsertionPhase().apply(graph); final SchedulePhase schedule = new SchedulePhase(); schedule.apply(graph); @@ -216,7 +220,7 @@ List<Block> codeEmittingOrder = ComputeBlockOrder.computeCodeEmittingOrder(blocks.length, startBlock); List<Block> linearScanOrder = ComputeBlockOrder.computeLinearScanOrder(blocks.length, startBlock); - LIR lir = new LIR(schedule.getCFG(), schedule.getBlockToNodesMap(), linearScanOrder, codeEmittingOrder); + LIR lir = new LIR(schedule.getCFG(), schedule.getBlockToNodesMap(), linearScanOrder, codeEmittingOrder, speculationLog); Debug.dump(lir, "After linear scan order"); return lir;
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/Interval.java Tue Mar 12 11:38:24 2013 +0100 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/Interval.java Tue Mar 12 11:38:52 2013 +0100 @@ -417,8 +417,8 @@ public final int operandNumber; /** - * The {@linkplain RegisterValue register}, {@linkplain StackSlot spill slot} or - * {@linkplain Address address} assigned to this interval. + * The {@linkplain RegisterValue register} or {@linkplain StackSlot spill slot} assigned to this + * interval. */ private Value location; @@ -515,8 +515,8 @@ } /** - * Gets the {@linkplain RegisterValue register}, {@linkplain StackSlot spill slot} or - * {@linkplain Address address} assigned to this interval. + * Gets the {@linkplain RegisterValue register} or {@linkplain StackSlot spill slot} assigned to + * this interval. */ public Value location() { return location;
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java Tue Mar 12 11:38:24 2013 +0100 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java Tue Mar 12 11:38:52 2013 +0100 @@ -347,6 +347,15 @@ return intervals[operandNumber]; } + Interval getOrCreateInterval(Value operand) { + Interval ret = intervalFor(operand); + if (ret == null) { + return createInterval(operand); + } else { + return ret; + } + } + /** * Gets the highest instruction id allocated by this object. */ @@ -968,11 +977,7 @@ TTY.println(" use %s from %d to %d (%s)", operand, from, to, registerPriority.name()); } - Interval interval = intervalFor(operand); - if (interval == null) { - interval = createInterval(operand); - } - + Interval interval = getOrCreateInterval(operand); if (kind != Kind.Illegal) { interval.setKind(kind); } @@ -990,11 +995,8 @@ if (GraalOptions.TraceLinearScanLevel >= 2) { TTY.println(" temp %s tempPos %d (%s)", operand, tempPos, RegisterPriority.MustHaveRegister.name()); } - Interval interval = intervalFor(operand); - if (interval == null) { - interval = createInterval(operand); - } + Interval interval = getOrCreateInterval(operand); if (kind != Kind.Illegal) { interval.setKind(kind); } @@ -1014,42 +1016,26 @@ if (GraalOptions.TraceLinearScanLevel >= 2) { TTY.println(" def %s defPos %d (%s)", operand, defPos, registerPriority.name()); } - Interval interval = intervalFor(operand); - if (interval != null) { - if (kind != Kind.Illegal) { - interval.setKind(kind); - } + Interval interval = getOrCreateInterval(operand); + if (kind != Kind.Illegal) { + interval.setKind(kind); + } - Range r = interval.first(); - if (r.from <= defPos) { - // Update the starting point (when a range is first created for a use, its - // start is the beginning of the current block until a def is encountered.) - r.from = defPos; - interval.addUsePos(defPos, registerPriority); - - } else { - // Dead value - make vacuous interval - // also add register priority for dead intervals - interval.addRange(defPos, defPos + 1); - interval.addUsePos(defPos, registerPriority); - if (GraalOptions.TraceLinearScanLevel >= 2) { - TTY.println("Warning: def of operand %s at %d occurs without use", operand, defPos); - } - } + Range r = interval.first(); + if (r.from <= defPos) { + // Update the starting point (when a range is first created for a use, its + // start is the beginning of the current block until a def is encountered.) + r.from = defPos; + interval.addUsePos(defPos, registerPriority); } else { // Dead value - make vacuous interval // also add register priority for dead intervals - interval = createInterval(operand); - if (kind != Kind.Illegal) { - interval.setKind(kind); - } - interval.addRange(defPos, defPos + 1); interval.addUsePos(defPos, registerPriority); if (GraalOptions.TraceLinearScanLevel >= 2) { - TTY.println("Warning: dead value %s at %d in live intervals", operand, defPos); + TTY.println("Warning: def of operand %s at %d occurs without use", operand, defPos); } } @@ -1114,7 +1100,7 @@ } } - void addRegisterHint(final LIRInstruction op, final Value targetValue, OperandMode mode, EnumSet<OperandFlag> flags) { + void addRegisterHint(final LIRInstruction op, final Value targetValue, OperandMode mode, EnumSet<OperandFlag> flags, final boolean hintAtDef) { if (flags.contains(OperandFlag.HINT) && isVariableOrRegister(targetValue)) { op.forEachRegisterHint(targetValue, mode, new ValueProcedure() { @@ -1122,15 +1108,20 @@ @Override protected Value doValue(Value registerHint) { if (isVariableOrRegister(registerHint)) { - Interval from = intervalFor(registerHint); - Interval to = intervalFor(targetValue); - if (from != null && to != null) { + Interval from = getOrCreateInterval(registerHint); + Interval to = getOrCreateInterval(targetValue); + + // hints always point from def to use + if (hintAtDef) { to.setLocationHint(from); - if (GraalOptions.TraceLinearScanLevel >= 4) { - TTY.println("operation at opId %d: added hint from interval %d to %d", op.id(), from.operandNumber, to.operandNumber); - } - return registerHint; + } else { + from.setLocationHint(to); } + + if (GraalOptions.TraceLinearScanLevel >= 4) { + TTY.println("operation at opId %d: added hint from interval %d to %d", op.id(), from.operandNumber, to.operandNumber); + } + return registerHint; } return null; } @@ -1201,7 +1192,7 @@ public Value doValue(Value operand, OperandMode mode, EnumSet<OperandFlag> flags) { if (isVariableOrRegister(operand)) { addDef(operand, opId, registerPriorityOfOutputOperand(op), operand.getKind().getStackKind()); - addRegisterHint(op, operand, mode, flags); + addRegisterHint(op, operand, mode, flags, true); } return operand; } @@ -1212,7 +1203,7 @@ public Value doValue(Value operand, OperandMode mode, EnumSet<OperandFlag> flags) { if (isVariableOrRegister(operand)) { addTemp(operand, opId, RegisterPriority.MustHaveRegister, operand.getKind().getStackKind()); - addRegisterHint(op, operand, mode, flags); + addRegisterHint(op, operand, mode, flags, false); } return operand; } @@ -1224,7 +1215,7 @@ if (isVariableOrRegister(operand)) { RegisterPriority p = registerPriorityOfInputOperand(flags); addUse(operand, blockFrom, opId + 1, p, operand.getKind().getStackKind()); - addRegisterHint(op, operand, mode, flags); + addRegisterHint(op, operand, mode, flags, false); } return operand; } @@ -1236,7 +1227,7 @@ if (isVariableOrRegister(operand)) { RegisterPriority p = registerPriorityOfInputOperand(flags); addUse(operand, blockFrom, opId, p, operand.getKind().getStackKind()); - addRegisterHint(op, operand, mode, flags); + addRegisterHint(op, operand, mode, flags, false); } return operand; }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/DebugInfoBuilder.java Tue Mar 12 11:38:24 2013 +0100 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/DebugInfoBuilder.java Tue Mar 12 11:38:52 2013 +0100 @@ -45,7 +45,7 @@ private HashMap<VirtualObjectNode, VirtualObject> virtualObjects = new HashMap<>(); private IdentityHashMap<VirtualObjectNode, EscapeObjectState> objectStates = new IdentityHashMap<>(); - public LIRFrameState build(FrameState topState, List<StackSlot> lockData, LabelRef exceptionEdge) { + public LIRFrameState build(FrameState topState, List<StackSlot> lockData, short reason, LabelRef exceptionEdge) { assert virtualObjects.size() == 0; assert objectStates.size() == 0; @@ -103,7 +103,7 @@ } objectStates.clear(); - return new LIRFrameState(frame, virtualObjectsArray, exceptionEdge); + return new LIRFrameState(frame, virtualObjectsArray, exceptionEdge, reason); } private BytecodeFrame computeFrameForState(FrameState state, List<StackSlot> lockDataSlots) {
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java Tue Mar 12 11:38:24 2013 +0100 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java Tue Mar 12 11:38:52 2013 +0100 @@ -231,19 +231,23 @@ } public LIRFrameState state() { + return state(null); + } + + public LIRFrameState state(DeoptimizationReason reason) { assert lastState != null || needOnlyOopMaps() : "must have state before instruction"; - return stateFor(lastState); + return stateFor(lastState, reason); } - public LIRFrameState stateFor(FrameState state) { - return stateFor(state, null); + public LIRFrameState stateFor(FrameState state, DeoptimizationReason reason) { + return stateForWithExceptionEdge(state, reason, null); } - public LIRFrameState stateFor(FrameState state, LabelRef exceptionEdge) { + public LIRFrameState stateForWithExceptionEdge(FrameState state, DeoptimizationReason reason, LabelRef exceptionEdge) { if (needOnlyOopMaps()) { - return new LIRFrameState(null, null, null); + return new LIRFrameState(null, null, null, (short) -1); } - return debugInfoBuilder.build(state, lockDataSlots.subList(0, currentLockCount), exceptionEdge); + return debugInfoBuilder.build(state, lockDataSlots.subList(0, currentLockCount), lir.getDeoptimizationReasons().addSpeculation(reason), exceptionEdge); } /** @@ -562,7 +566,7 @@ for (PhiNode phi : merge.phis()) { if (phi.type() == PhiType.Value) { ValueNode curVal = phi.valueAt(pred); - resolver.move(operand(curVal), operandForPhi(phi)); + resolver.move(operandForPhi(phi), operand(curVal)); } } resolver.dispose(); @@ -590,15 +594,13 @@ @Override public void emitGuardCheck(LogicNode comp, DeoptimizationReason deoptReason, DeoptimizationAction action, boolean negated) { - if (comp instanceof IsNullNode && negated) { - emitNullCheckGuard(((IsNullNode) comp).object()); - } else if (comp instanceof LogicConstantNode && ((LogicConstantNode) comp).getValue() != negated) { + if (comp instanceof LogicConstantNode && ((LogicConstantNode) comp).getValue() != negated) { // True constant, nothing to emit. // False constants are handled within emitBranch. } else { // Fall back to a normal branch. - LIRFrameState info = state(); - LabelRef stubEntry = createDeoptStub(action, deoptReason, info, comp); + LIRFrameState info = state(deoptReason); + LabelRef stubEntry = createDeoptStub(action, deoptReason, info); if (negated) { emitBranch(comp, stubEntry, null, info); } else { @@ -607,8 +609,6 @@ } } - protected abstract void emitNullCheckGuard(ValueNode object); - public void emitBranch(LogicNode node, LabelRef trueSuccessor, LabelRef falseSuccessor, LIRFrameState info) { if (node instanceof IsNullNode) { emitNullCheckBranch((IsNullNode) node, trueSuccessor, falseSuccessor, info); @@ -645,6 +645,17 @@ } } + public void emitOverflowCheckBranch(LabelRef noOverflowBlock, LabelRef overflowBlock, LIRFrameState info) { + if (overflowBlock != null) { + emitOverflowCheckBranch(overflowBlock, info, false); + if (noOverflowBlock != null) { + emitJump(noOverflowBlock, null); + } + } else { + emitOverflowCheckBranch(noOverflowBlock, info, true); + } + } + public void emitIntegerTestBranch(IntegerTestNode test, LabelRef trueSuccessorBlock, LabelRef falseSuccessorBlock, LIRFrameState info) { if (falseSuccessorBlock != null) { emitIntegerTestBranch(operand(test.x()), operand(test.y()), true, falseSuccessorBlock, info); @@ -691,6 +702,8 @@ public abstract void emitCompareBranch(Value left, Value right, Condition cond, boolean unorderedIsTrue, LabelRef label, LIRFrameState info); + public abstract void emitOverflowCheckBranch(LabelRef label, LIRFrameState info, boolean negated); + public abstract void emitIntegerTestBranch(Value left, Value right, boolean negated, LabelRef label, LIRFrameState info); public abstract Variable emitConditionalMove(Value leftVal, Value right, Condition cond, boolean unorderedIsTrue, Value trueValue, Value falseValue); @@ -707,7 +720,7 @@ LIRFrameState callState = null; if (x.stateAfter() != null) { - callState = stateFor(x.stateDuring(), x instanceof InvokeWithExceptionNode ? getLIRBlock(((InvokeWithExceptionNode) x).exceptionEdge()) : null); + callState = stateForWithExceptionEdge(x.stateDuring(), null, x instanceof InvokeWithExceptionNode ? getLIRBlock(((InvokeWithExceptionNode) x).exceptionEdge()) : null); } Value result = cc.getReturn(); @@ -763,7 +776,7 @@ return result; } - protected abstract LabelRef createDeoptStub(DeoptimizationAction action, DeoptimizationReason reason, LIRFrameState info, Object deoptInfo); + protected abstract LabelRef createDeoptStub(DeoptimizationAction action, DeoptimizationReason reason, LIRFrameState info); @Override public Variable emitCall(RuntimeCallTarget callTarget, CallingConvention cc, boolean canTrap, Value... args) { @@ -809,7 +822,7 @@ if ((stateAfter.stackSize() > 0 && stateAfter.stackAt(stateAfter.stackSize() - 1) == x) || (stateAfter.stackSize() > 1 && stateAfter.stackAt(stateAfter.stackSize() - 2) == x)) { stateBeforeReturn = stateAfter.duplicateModified(stateAfter.bci, stateAfter.rethrowException(), x.kind()); } - info = stateFor(stateBeforeReturn); + info = stateFor(stateBeforeReturn, null); } else { info = state(); }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/PhiResolver.java Tue Mar 12 11:38:24 2013 +0100 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/PhiResolver.java Tue Mar 12 11:38:52 2013 +0100 @@ -131,7 +131,7 @@ PhiResolverNode node = variableOperands.get(i); if (!node.visited) { loop = null; - move(null, node); + move(node, null); node.startNode = true; assert isIllegal(temp) : "moveTempTo() call missing"; } @@ -141,12 +141,12 @@ for (int i = otherOperands.size() - 1; i >= 0; i--) { PhiResolverNode node = otherOperands.get(i); for (int j = node.destinations.size() - 1; j >= 0; j--) { - emitMove(node.operand, node.destinations.get(j).operand); + emitMove(node.destinations.get(j).operand, node.operand); } } } - public void move(Value src, Value dest) { + public void move(Value dest, Value src) { assert isVariable(dest) : "destination must be virtual"; // tty.print("move "); src.print(); tty.print(" to "); dest.print(); tty.cr(); assert isLegal(src) : "source for phi move is illegal"; @@ -184,7 +184,7 @@ return createNode(opr, false); } - private void emitMove(Value src, Value dest) { + private void emitMove(Value dest, Value src) { assert isLegal(src); assert isLegal(dest); gen.emitMove(dest, src); @@ -192,16 +192,16 @@ // Traverse assignment graph in depth first order and generate moves in post order // ie. two assignments: b := c, a := b start with node c: - // Call graph: move(NULL, c) -> move(c, b) -> move(b, a) + // Call graph: move(c, NULL) -> move(b, c) -> move(a, b) // Generates moves in this order: move b to a and move c to b // ie. cycle a := b, b := a start with node a - // Call graph: move(NULL, a) -> move(a, b) -> move(b, a) + // Call graph: move(a, NULL) -> move(b, a) -> move(a, b) // Generates moves in this order: move b to temp, move a to b, move temp to a - private void move(PhiResolverNode src, PhiResolverNode dest) { + private void move(PhiResolverNode dest, PhiResolverNode src) { if (!dest.visited) { dest.visited = true; for (int i = dest.destinations.size() - 1; i >= 0; i--) { - move(dest, dest.destinations.get(i)); + move(dest.destinations.get(i), dest); } } else if (!dest.startNode) { // cycle in graph detected @@ -216,7 +216,7 @@ moveTempTo(dest.operand); dest.assigned = true; } else if (src != null) { - emitMove(src.operand, dest.operand); + emitMove(dest.operand, src.operand); dest.assigned = true; } } @@ -224,14 +224,14 @@ private void moveTempTo(Value dest) { assert isLegal(temp); - emitMove(temp, dest); + emitMove(dest, temp); temp = ILLEGAL; } private void moveToTemp(Value src) { assert isIllegal(temp); temp = gen.newVariable(src.getKind()); - emitMove(src, temp); + emitMove(temp, src); } private PhiResolverNode sourceNode(Value opr) {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64DeoptimizeOp.java Tue Mar 12 11:38:52 2013 +0100 @@ -0,0 +1,55 @@ +/* + * 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 com.oracle.graal.hotspot.amd64; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.code.RuntimeCallTarget.Descriptor; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.asm.amd64.*; +import com.oracle.graal.lir.*; +import com.oracle.graal.lir.LIRInstruction.Opcode; +import com.oracle.graal.lir.amd64.*; +import com.oracle.graal.lir.asm.*; + +@Opcode("DEOPT") +final class AMD64DeoptimizeOp extends AMD64LIRInstruction { + + public static final Descriptor DEOPTIMIZE = new Descriptor("deoptimize", true, void.class); + + private DeoptimizationAction action; + private DeoptimizationReason reason; + @State private LIRFrameState info; + + AMD64DeoptimizeOp(DeoptimizationAction action, DeoptimizationReason reason, LIRFrameState info) { + this.action = action; + this.reason = reason; + this.info = info; + } + + @Override + public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { + Register scratch = tasm.frameMap.registerConfig.getScratchRegister(); + masm.movl(scratch, tasm.runtime.encodeDeoptActionAndReason(action, reason)); + AMD64Call.directCall(tasm, masm, tasm.runtime.lookupRuntimeCall(DEOPTIMIZE), info); + } +}
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64DirectCallOp.java Tue Mar 12 11:38:24 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,123 +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 com.oracle.graal.hotspot.amd64; - -import static com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind.*; - -import com.oracle.graal.amd64.*; -import com.oracle.graal.api.code.CompilationResult.Mark; -import com.oracle.graal.api.meta.*; -import com.oracle.graal.asm.amd64.*; -import com.oracle.graal.hotspot.bridge.*; -import com.oracle.graal.lir.*; -import com.oracle.graal.lir.LIRInstruction.Opcode; -import com.oracle.graal.lir.amd64.*; -import com.oracle.graal.lir.amd64.AMD64Call.DirectCallOp; -import com.oracle.graal.lir.asm.*; -import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind; - -/** - * A direct call that complies with the conventions for such calls in HotSpot. In particular, for - * calls using an inline cache, a MOVE instruction is emitted just prior to the aligned direct call. - * This instruction (which moves 0L in RAX) is patched by the C++ Graal code to replace the 0L - * constant with Universe::non_oop_word(), a special sentinel used for the initial value of the - * Klass in an inline cache. - * <p> - * For non-inline cache calls (i.e., INVOKESTATIC and INVOKESPECIAL), a static call stub is emitted. - * Initially, these calls go to the global static call resolution stub (i.e., - * SharedRuntime::get_resolve_static_call_stub()). Resolution will link the call to a compiled - * version of the callee if available otherwise to the interpreter. The interpreter expects to find - * the Method* for the callee in RBX. To achieve this, the static call is linked to a static call - * stub which initializes RBX and jumps to the interpreter. This pattern is shown below: - * - * <pre> - * call L1 - * nop - * - * ... - * - * L1: mov rbx [Method*] - * jmp [interpreter entry point] - * </pre> - */ -@Opcode("CALL_DIRECT") -final class AMD64DirectCallOp extends DirectCallOp { - - /** - * The mark emitted at the position of the direct call instruction. This is only recorded for - * calls that have an associated static call stub (i.e., - * {@code invokeKind == Static || invokeKind == Special}). - */ - Mark callsiteMark; - - private final InvokeKind invokeKind; - - AMD64DirectCallOp(InvokeTarget target, Value result, Value[] parameters, Value[] temps, LIRFrameState state, InvokeKind invokeKind, LIR lir) { - super(target, result, parameters, temps, state); - this.invokeKind = invokeKind; - - if (invokeKind == Static || invokeKind == Special) { - lir.stubs.add(new AMD64Code() { - - public String description() { - return "static call stub for Invoke" + AMD64DirectCallOp.this.invokeKind; - } - - @Override - public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - assert callsiteMark != null : "static call site has not yet been emitted"; - tasm.recordMark(Marks.MARK_STATIC_CALL_STUB, callsiteMark); - masm.movq(AMD64.rbx, 0L); - int pos = masm.codeBuffer.position(); - // Create a jump-to-self as expected by CompiledStaticCall::set_to_interpreted() - // in compiledIC.cpp - masm.jmp(pos, true); - } - }); - } - - } - - @Override - public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - if (invokeKind == Static || invokeKind == Special) { - tasm.recordMark(invokeKind == Static ? Marks.MARK_INVOKESTATIC : Marks.MARK_INVOKESPECIAL); - } else { - assert invokeKind == Virtual || invokeKind == Interface; - // The mark for an invocation that uses an inline cache must be placed at the - // instruction - // that loads the Klass from the inline cache so that the C++ code can find it - // and replace the inline 0L value with Universe::non_oop_word() - tasm.recordMark(invokeKind == Virtual ? Marks.MARK_INVOKEVIRTUAL : Marks.MARK_INVOKEINTERFACE); - AMD64Move.move(tasm, masm, AMD64.rax.asValue(Kind.Long), Constant.LONG_0); - } - - emitAlignmentForDirectCall(tasm, masm); - - if (invokeKind == Static || invokeKind == Special) { - callsiteMark = tasm.recordMark(null); - } - - AMD64Call.directCall(tasm, masm, callTarget, state); - } -}
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java Tue Mar 12 11:38:24 2013 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java Tue Mar 12 11:38:52 2013 +0100 @@ -25,7 +25,6 @@ import static com.oracle.graal.amd64.AMD64.*; import static com.oracle.graal.api.code.CallingConvention.Type.*; import static com.oracle.graal.api.code.ValueUtil.*; -import static com.oracle.graal.phases.GraalOptions.*; import java.lang.reflect.*; @@ -33,11 +32,12 @@ import com.oracle.graal.amd64.*; import com.oracle.graal.api.code.*; -import com.oracle.graal.api.code.RuntimeCallTarget.*; +import com.oracle.graal.api.code.RuntimeCallTarget.Descriptor; import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.*; +import com.oracle.graal.asm.amd64.*; +import com.oracle.graal.asm.amd64.AMD64Address.Scale; import com.oracle.graal.asm.amd64.AMD64Assembler.ConditionFlag; -import com.oracle.graal.asm.amd64.*; import com.oracle.graal.compiler.amd64.*; import com.oracle.graal.compiler.gen.*; import com.oracle.graal.hotspot.*; @@ -51,6 +51,7 @@ import com.oracle.graal.lir.asm.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.java.*; +import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind; import com.oracle.graal.phases.*; /** @@ -105,7 +106,7 @@ @Override public void visitSafepointNode(SafepointNode i) { LIRFrameState info = state(); - append(new AMD64SafepointOp(info, runtime().config)); + append(new AMD64SafepointOp(info, runtime().config, this)); } @Override @@ -128,14 +129,14 @@ Variable newVal = load(operand(x.newValue())); int disp = 0; - AMD64Address address; + AMD64AddressValue address; Value index = operand(x.offset()); if (ValueUtil.isConstant(index) && NumUtil.isInt(ValueUtil.asConstant(index).asLong() + disp)) { assert !runtime.needsDataPatch(asConstant(index)); disp += (int) ValueUtil.asConstant(index).asLong(); - address = new AMD64Address(kind, load(operand(x.object())), disp); + address = new AMD64AddressValue(kind, load(operand(x.object())), disp); } else { - address = new AMD64Address(kind, load(operand(x.object())), load(index), AMD64Address.Scale.Times1, disp); + address = new AMD64AddressValue(kind, load(operand(x.object())), load(index), Scale.Times1, disp); } RegisterValue rax = AMD64.rax.asValue(kind); @@ -155,7 +156,15 @@ @Override protected void emitDirectCall(DirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) { - append(new AMD64DirectCallOp(callTarget.target(), result, parameters, temps, callState, ((HotSpotDirectCallTargetNode) callTarget).invokeKind(), lir)); + InvokeKind invokeKind = ((HotSpotDirectCallTargetNode) callTarget).invokeKind(); + if (invokeKind == InvokeKind.Interface || invokeKind == InvokeKind.Virtual) { + append(new AMD64HotspotDirectVirtualCallOp(callTarget.target(), result, parameters, temps, callState, invokeKind)); + } else { + assert invokeKind == InvokeKind.Static || invokeKind == InvokeKind.Special; + HotSpotResolvedJavaMethod resolvedMethod = (HotSpotResolvedJavaMethod) callTarget.target(); + Constant metaspaceMethod = resolvedMethod.getMetaspaceMethodConstant(); + append(new AMD64HotspotDirectStaticCallOp(callTarget.target(), result, parameters, temps, callState, invokeKind, metaspaceMethod)); + } } @Override @@ -166,6 +175,18 @@ emitMove(targetAddress, operand(callTarget.computedAddress())); append(new AMD64IndirectCallOp(callTarget.target(), result, parameters, temps, metaspaceMethod, targetAddress, callState)); } + + @Override + public void emitUnwind(Value exception) { + RegisterValue exceptionParameter = AMD64.rax.asValue(); + emitMove(exceptionParameter, exception); + append(new AMD64HotSpotUnwindOp(exceptionParameter)); + } + + @Override + public void emitDeoptimize(DeoptimizationAction action, DeoptimizationReason reason) { + append(new AMD64DeoptimizeOp(action, reason, state(reason))); + } } /** @@ -188,7 +209,7 @@ disp -= frameSize; } tasm.blockComment("[stack overflow check]"); - asm.movq(new AMD64Address(asm.target.wordKind, AMD64.RSP, -disp), AMD64.rax); + asm.movq(new AMD64Address(rsp, -disp), AMD64.rax); } } } @@ -204,12 +225,11 @@ AMD64MacroAssembler asm = (AMD64MacroAssembler) tasm.asm; emitStackOverflowCheck(tasm, false); asm.push(rbp); - asm.movq(rbp, rsp); asm.decrementq(rsp, frameSize - 8); // account for the push of RBP above if (GraalOptions.ZapStackOnMethodEntry) { final int intSize = 4; for (int i = 0; i < frameSize / intSize; ++i) { - asm.movl(new AMD64Address(Kind.Int, rsp.asValue(), i * intSize), 0xC1C1C1C1); + asm.movl(new AMD64Address(rsp, i * intSize), 0xC1C1C1C1); } } CalleeSaveLayout csl = frameMap.registerConfig.getCalleeSaveLayout(); @@ -225,7 +245,6 @@ int frameSize = tasm.frameMap.frameSize(); AMD64MacroAssembler asm = (AMD64MacroAssembler) tasm.asm; CalleeSaveLayout csl = tasm.frameMap.registerConfig.getCalleeSaveLayout(); - RegisterConfig regConfig = tasm.frameMap.registerConfig; if (csl != null && csl.size != 0) { tasm.compilationResult.setRegisterRestoreEpilogueOffset(asm.codeBuffer.position()); @@ -236,27 +255,6 @@ asm.incrementq(rsp, frameSize - 8); // account for the pop of RBP below asm.pop(rbp); - - if (GraalOptions.GenSafepoints) { - HotSpotVMConfig config = runtime().config; - - // If at the return point, then the frame has already been popped - // so deoptimization cannot be performed here. The HotSpot runtime - // detects this case - see the definition of frame::should_be_deoptimized() - - Register scratch = regConfig.getScratchRegister(); - int offset = SafepointPollOffset % unsafe.pageSize(); - if (config.isPollingPageFar) { - asm.movq(scratch, config.safepointPollingAddress + offset); - tasm.recordMark(Marks.MARK_POLL_RETURN_FAR); - asm.movq(scratch, new AMD64Address(tasm.target.wordKind, scratch.asValue())); - } else { - tasm.recordMark(Marks.MARK_POLL_RETURN_NEAR); - // The C++ code transforms the polling page offset into an RIP displacement - // to the real address at that offset in the polling page. - asm.movq(scratch, new AMD64Address(tasm.target.wordKind, rip.asValue(), offset)); - } - } } } @@ -272,7 +270,7 @@ AbstractAssembler masm = new AMD64MacroAssembler(target, frameMap.registerConfig); HotSpotFrameContext frameContext = omitFrame ? null : new HotSpotFrameContext(); - TargetMethodAssembler tasm = new TargetMethodAssembler(target, runtime(), frameMap, masm, frameContext, lir.stubs); + TargetMethodAssembler tasm = new TargetMethodAssembler(target, runtime(), frameMap, masm, frameContext); tasm.setFrameSize(frameMap.frameSize()); tasm.compilationResult.setCustomStackAreaOffset(frameMap.offsetToCustomArea()); return tasm; @@ -295,7 +293,7 @@ Register inlineCacheKlass = rax; // see definition of IC_Klass in // c1_LIRAssembler_x86.cpp Register receiver = asRegister(cc.getArgument(0)); - AMD64Address src = new AMD64Address(target.wordKind, receiver.asValue(), config.hubOffset); + AMD64Address src = new AMD64Address(receiver, config.hubOffset); asm.cmpq(inlineCacheKlass, src); asm.jcc(ConditionFlag.NotEqual, unverifiedStub); @@ -312,11 +310,9 @@ if (!frameOmitted) { tasm.recordMark(Marks.MARK_EXCEPTION_HANDLER_ENTRY); AMD64Call.directCall(tasm, asm, runtime().lookupRuntimeCall(EXCEPTION_HANDLER), null); - AMD64Call.shouldNotReachHere(tasm, asm); tasm.recordMark(Marks.MARK_DEOPT_HANDLER_ENTRY); AMD64Call.directCall(tasm, asm, runtime().lookupRuntimeCall(DEOPT_HANDLER), null); - AMD64Call.shouldNotReachHere(tasm, asm); } else { // No need to emit the stubs for entries back into the method since // it has no calls that can cause such "return" entries
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRegisterConfig.java Tue Mar 12 11:38:24 2013 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRegisterConfig.java Tue Mar 12 11:38:52 2013 +0100 @@ -37,9 +37,8 @@ // @formatter:off public class AMD64HotSpotRegisterConfig implements RegisterConfig { - // be careful - the contents of this array are duplicated in graal_CodeInstaller.cpp private final Register[] allocatable = { - rax, rbx, rcx, rdx, rsi, rdi, r8, r9, /* r10, */r11, r12, r13, r14, /*r15*/ + rax, rbx, rcx, rdx, /*rsp,*/ rbp, rsi, rdi, r8, r9, /* r10, */r11, r12, r13, r14, /*r15, */ xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15 }; @@ -209,8 +208,7 @@ String res = String.format( "Allocatable: " + Arrays.toString(getAllocatableRegisters()) + "%n" + "CallerSave: " + Arrays.toString(getCallerSaveRegisters()) + "%n" + - "CalleeSave: " + getCalleeSaveLayout() + "%n" + - "Scratch: " + getScratchRegister() + "%n"); + "CalleeSave: " + getCalleeSaveLayout() + "%n"); return res; } }
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRuntime.java Tue Mar 12 11:38:24 2013 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRuntime.java Tue Mar 12 11:38:52 2013 +0100 @@ -23,8 +23,8 @@ package com.oracle.graal.hotspot.amd64; import static com.oracle.graal.amd64.AMD64.*; -import static com.oracle.graal.compiler.amd64.AMD64DeoptimizationStub.*; import static com.oracle.graal.compiler.amd64.AMD64LIRGenerator.*; +import static com.oracle.graal.hotspot.amd64.AMD64DeoptimizeOp.*; import static com.oracle.graal.hotspot.nodes.IdentityHashCodeStubCall.*; import static com.oracle.graal.hotspot.nodes.MonitorEnterStubCall.*; import static com.oracle.graal.hotspot.nodes.MonitorExitStubCall.*; @@ -40,12 +40,17 @@ import static com.oracle.graal.hotspot.snippets.AESCryptSubstitutions.EncryptBlockStubCall.*; import static com.oracle.graal.hotspot.snippets.CipherBlockChainingSubstitutions.DecryptAESCryptStubCall.*; import static com.oracle.graal.hotspot.snippets.CipherBlockChainingSubstitutions.EncryptAESCryptStubCall.*; -import static com.oracle.graal.lir.amd64.AMD64Call.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.target.*; +import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.*; +import com.oracle.graal.hotspot.amd64.snippets.*; import com.oracle.graal.hotspot.meta.*; +import com.oracle.graal.nodes.calc.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.snippets.*; public class AMD64HotSpotRuntime extends HotSpotRuntime { @@ -55,20 +60,15 @@ Kind word = graalRuntime.getTarget().wordKind; // @formatter:off + addRuntimeCall(AMD64HotSpotUnwindOp.UNWIND_EXCEPTION, config.unwindExceptionStub, + /* temps */ null, + /* ret */ ret(Kind.Void), + /* arg0: exception */ javaCallingConvention(Kind.Object)); addRuntimeCall(DEOPTIMIZE, config.deoptimizeStub, /* temps */ null, /* ret */ ret(Kind.Void)); - addRuntimeCall(SET_DEOPT_INFO, config.setDeoptInfoStub, - /* temps */ null, - /* ret */ ret(Kind.Void), - /* arg0: info */ scratch(Kind.Object)); - - addRuntimeCall(DEBUG, config.debugStub, - /* temps */ null, - /* ret */ ret(Kind.Void)); - addRuntimeCall(ARITHMETIC_FREM, config.arithmeticFremStub, /* temps */ null, /* ret */ ret(Kind.Float), @@ -192,6 +192,24 @@ } + private AMD64ConvertSnippets.Templates convertSnippets; + + @Override + public void installSnippets(Backend backend, SnippetInstaller installer, Assumptions assumptions) { + installer.installSnippets(AMD64ConvertSnippets.class); + convertSnippets = new AMD64ConvertSnippets.Templates(this, assumptions, graalRuntime.getTarget()); + super.installSnippets(backend, installer, assumptions); + } + + @Override + public void lower(Node n, LoweringTool tool) { + if (n instanceof ConvertNode) { + convertSnippets.lower((ConvertNode) n, tool); + } else { + super.lower(n, tool); + } + } + @Override public Register threadRegister() { return r15;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotUnwindOp.java Tue Mar 12 11:38:52 2013 +0100 @@ -0,0 +1,64 @@ +/* + * 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 com.oracle.graal.hotspot.amd64; + +import static com.oracle.graal.amd64.AMD64.*; +import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; + +import com.oracle.graal.amd64.*; +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.code.RuntimeCallTarget.*; +import com.oracle.graal.asm.amd64.*; +import com.oracle.graal.lir.LIRInstruction.Opcode; +import com.oracle.graal.lir.amd64.*; +import com.oracle.graal.lir.asm.*; + +/** + * Performs an unwind to throw an exception. + */ +@Opcode("CALL_INDIRECT") +final class AMD64HotSpotUnwindOp extends AMD64LIRInstruction { + + public static final Descriptor UNWIND_EXCEPTION = new Descriptor("unwindException", true, void.class, Object.class); + + /** + * Vtable stubs expect the metaspace Method in RBX. + */ + public static final Register METHOD = AMD64.rbx; + + @Use({REG}) protected AllocatableValue exception; + @Temp private RegisterValue framePointer; + + AMD64HotSpotUnwindOp(AllocatableValue exception) { + this.exception = exception; + assert exception == AMD64.rax.asValue(); + framePointer = AMD64.rbp.asValue(); + } + + @Override + public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { + masm.movq(framePointer.getRegister(), rsp); + masm.incrementq(framePointer.getRegister(), tasm.frameMap.frameSize() - 8); + AMD64Call.directCall(tasm, masm, tasm.runtime.lookupRuntimeCall(UNWIND_EXCEPTION), null); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotspotDirectStaticCallOp.java Tue Mar 12 11:38:52 2013 +0100 @@ -0,0 +1,67 @@ +/* + * 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 com.oracle.graal.hotspot.amd64; + +import com.oracle.graal.amd64.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.asm.amd64.*; +import com.oracle.graal.hotspot.bridge.*; +import com.oracle.graal.lir.*; +import com.oracle.graal.lir.LIRInstruction.Opcode; +import com.oracle.graal.lir.amd64.*; +import com.oracle.graal.lir.amd64.AMD64Call.DirectCallOp; +import com.oracle.graal.lir.asm.*; +import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind; + +/** + * A direct call that complies with the conventions for such calls in HotSpot. In particular, for + * calls using an inline cache, a MOVE instruction is emitted just prior to the aligned direct call. + * This instruction (which moves 0L in RAX) is patched by the C++ Graal code to replace the 0L + * constant with Universe::non_oop_word(), a special sentinel used for the initial value of the + * Klass in an inline cache. It puts the called method into rbx before calling. + */ +@Opcode("CALL_DIRECT") +final class AMD64HotspotDirectStaticCallOp extends DirectCallOp { + + private final Constant metaspaceMethod; + private final InvokeKind invokeKind; + + AMD64HotspotDirectStaticCallOp(InvokeTarget target, Value result, Value[] parameters, Value[] temps, LIRFrameState state, InvokeKind invokeKind, Constant metaspaceMethod) { + super(target, result, parameters, temps, state); + assert invokeKind == InvokeKind.Static || invokeKind == InvokeKind.Special; + this.metaspaceMethod = metaspaceMethod; + this.invokeKind = invokeKind; + } + + @Override + public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { + // The mark for an invocation that uses an inline cache must be placed at the + // instruction + // that loads the Klass from the inline cache so that the C++ code can find it + // and replace the inline 0L value with Universe::non_oop_word() + AMD64Move.move(tasm, masm, AMD64.rbx.asValue(Kind.Long), metaspaceMethod); + tasm.recordMark(invokeKind == InvokeKind.Static ? Marks.MARK_INVOKESTATIC : Marks.MARK_INVOKESPECIAL); + AMD64Move.move(tasm, masm, AMD64.rax.asValue(Kind.Long), Constant.LONG_0); + super.emitCode(tasm, masm); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotspotDirectVirtualCallOp.java Tue Mar 12 11:38:52 2013 +0100 @@ -0,0 +1,66 @@ +/* + * 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 com.oracle.graal.hotspot.amd64; + +import static com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind.*; + +import com.oracle.graal.amd64.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.asm.amd64.*; +import com.oracle.graal.hotspot.bridge.*; +import com.oracle.graal.lir.*; +import com.oracle.graal.lir.LIRInstruction.Opcode; +import com.oracle.graal.lir.amd64.*; +import com.oracle.graal.lir.amd64.AMD64Call.DirectCallOp; +import com.oracle.graal.lir.asm.*; +import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind; + +/** + * A direct call that complies with the conventions for such calls in HotSpot. In particular, for + * calls using an inline cache, a MOVE instruction is emitted just prior to the aligned direct call. + * This instruction (which moves 0L in RAX) is patched by the C++ Graal code to replace the 0L + * constant with Universe::non_oop_word(), a special sentinel used for the initial value of the + * Klass in an inline cache. + */ +@Opcode("CALL_DIRECT") +final class AMD64HotspotDirectVirtualCallOp extends DirectCallOp { + + private final InvokeKind invokeKind; + + AMD64HotspotDirectVirtualCallOp(InvokeTarget target, Value result, Value[] parameters, Value[] temps, LIRFrameState state, InvokeKind invokeKind) { + super(target, result, parameters, temps, state); + this.invokeKind = invokeKind; + assert invokeKind == InvokeKind.Interface || invokeKind == InvokeKind.Virtual; + } + + @Override + public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { + // The mark for an invocation that uses an inline cache must be placed at the + // instruction + // that loads the Klass from the inline cache so that the C++ code can find it + // and replace the inline 0L value with Universe::non_oop_word() + tasm.recordMark(invokeKind == Virtual ? Marks.MARK_INVOKEVIRTUAL : Marks.MARK_INVOKEINTERFACE); + AMD64Move.move(tasm, masm, AMD64.rax.asValue(Kind.Long), Constant.LONG_0); + super.emitCode(tasm, masm); + } +}
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64IndirectCallOp.java Tue Mar 12 11:38:24 2013 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64IndirectCallOp.java Tue Mar 12 11:38:52 2013 +0100 @@ -59,7 +59,7 @@ @Override public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - tasm.recordMark(Marks.MARK_INLINE_INVOKEVIRTUAL); + tasm.recordMark(Marks.MARK_INLINE_INVOKE); Register callReg = asRegister(targetAddress); assert callReg != METHOD; AMD64Call.indirectCall(tasm, masm, callReg, callTarget, state);
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64SafepointOp.java Tue Mar 12 11:38:24 2013 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64SafepointOp.java Tue Mar 12 11:38:52 2013 +0100 @@ -26,7 +26,6 @@ import static com.oracle.graal.phases.GraalOptions.*; import sun.misc.*; -import com.oracle.graal.amd64.*; import com.oracle.graal.api.code.*; import com.oracle.graal.asm.amd64.*; import com.oracle.graal.hotspot.*; @@ -35,6 +34,7 @@ import com.oracle.graal.lir.LIRInstruction.Opcode; import com.oracle.graal.lir.amd64.*; import com.oracle.graal.lir.asm.*; +import com.oracle.graal.nodes.spi.*; /** * Emits a safepoint poll. @@ -45,30 +45,32 @@ private static final Unsafe unsafe = Unsafe.getUnsafe(); @State protected LIRFrameState state; + @Temp({OperandFlag.REG}) private AllocatableValue temp; private final HotSpotVMConfig config; - public AMD64SafepointOp(LIRFrameState state, HotSpotVMConfig config) { + public AMD64SafepointOp(LIRFrameState state, HotSpotVMConfig config, LIRGeneratorTool tool) { this.state = state; this.config = config; + temp = tool.newVariable(tool.target().wordKind); } @Override public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler asm) { - Register scratch = tasm.frameMap.registerConfig.getScratchRegister(); int pos = asm.codeBuffer.position(); int offset = SafepointPollOffset % unsafe.pageSize(); + RegisterValue scratch = (RegisterValue) temp; if (config.isPollingPageFar) { - asm.movq(scratch, config.safepointPollingAddress + offset); + asm.movq(scratch.getRegister(), config.safepointPollingAddress + offset); tasm.recordMark(Marks.MARK_POLL_FAR); tasm.recordSafepoint(pos, state); - asm.movq(scratch, new AMD64Address(tasm.target.wordKind, scratch.asValue())); + asm.movq(scratch.getRegister(), new AMD64Address(scratch.getRegister())); } else { tasm.recordMark(Marks.MARK_POLL_NEAR); tasm.recordSafepoint(pos, state); // The C++ code transforms the polling page offset into an RIP displacement // to the real address at that offset in the polling page. - asm.movq(scratch, new AMD64Address(tasm.target.wordKind, rip.asValue(), offset)); + asm.movq(scratch.getRegister(), new AMD64Address(rip, offset)); } } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/snippets/AMD64ConvertSnippets.java Tue Mar 12 11:38:52 2013 +0100 @@ -0,0 +1,196 @@ +/* + * 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.graal.hotspot.amd64.snippets; + +import static com.oracle.graal.snippets.SnippetTemplate.*; +import static com.oracle.graal.snippets.SnippetTemplate.Arguments.*; +import static com.oracle.graal.snippets.nodes.BranchProbabilityNode.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.debug.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.*; +import com.oracle.graal.nodes.calc.ConvertNode.Op; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.snippets.*; +import com.oracle.graal.snippets.Snippet.Parameter; +import com.oracle.graal.snippets.SnippetTemplate.AbstractTemplates; +import com.oracle.graal.snippets.SnippetTemplate.Arguments; +import com.oracle.graal.snippets.SnippetTemplate.Key; + +/** + * Snippets used for conversion operations on AMD64 where the AMD64 instruction used does not match + * the semantics of the JVM specification. + */ +public class AMD64ConvertSnippets implements SnippetsInterface { + + /** + * Converts a float to an int. + * <p> + * This snippet accounts for the semantics of the x64 CVTTSS2SI instruction used to do the + * conversion. If the float value is a NaN, infinity or if the result of the conversion is + * larger than {@link Integer#MAX_VALUE} then CVTTSS2SI returns {@link Integer#MIN_VALUE} and + * extra tests are required on the float value to return the correct int value. + * + * @param input the float being converted + * @param result the result produced by the CVTTSS2SI instruction + */ + @Snippet + public static int f2i(@Parameter("input") float input, @Parameter("result") int result) { + if (result == Integer.MIN_VALUE) { + probability(NOT_FREQUENT_PROBABILITY); + if (Float.isNaN(input)) { + // input is NaN -> return 0 + return 0; + } else if (input > 0.0f) { + // input is > 0 -> return max int + return Integer.MAX_VALUE; + } + } + return result; + } + + /** + * Converts a float to a long. + * <p> + * This snippet accounts for the semantics of the x64 CVTTSS2SI instruction used to do the + * conversion. If the float value is a NaN or infinity then CVTTSS2SI returns + * {@link Long#MIN_VALUE} and extra tests are required on the float value to return the correct + * long value. + * + * @param input the float being converted + * @param result the result produced by the CVTTSS2SI instruction + */ + @Snippet + public static long f2l(@Parameter("input") float input, @Parameter("result") long result) { + if (result == Long.MIN_VALUE) { + probability(NOT_FREQUENT_PROBABILITY); + if (Float.isNaN(input)) { + // input is NaN -> return 0 + return 0; + } else if (input > 0.0f) { + // input is > 0 -> return max int + return Long.MAX_VALUE; + } + } + return result; + } + + /** + * Converts a double to an int. + * <p> + * This snippet accounts for the semantics of the x64 CVTTSD2SI instruction used to do the + * conversion. If the double value is a NaN, infinity or if the result of the conversion is + * larger than {@link Integer#MAX_VALUE} then CVTTSD2SI returns {@link Integer#MIN_VALUE} and + * extra tests are required on the double value to return the correct int value. + * + * @param input the double being converted + * @param result the result produced by the CVTTSS2SI instruction + */ + @Snippet + public static int d2i(@Parameter("input") double input, @Parameter("result") int result) { + if (result == Integer.MIN_VALUE) { + probability(NOT_FREQUENT_PROBABILITY); + if (Double.isNaN(input)) { + // input is NaN -> return 0 + return 0; + } else if (input > 0.0d) { + // input is positive -> return maxInt + return Integer.MAX_VALUE; + } + } + return result; + } + + /** + * Converts a double to a long. + * <p> + * This snippet accounts for the semantics of the x64 CVTTSD2SI instruction used to do the + * conversion. If the double value is a NaN, infinity or if the result of the conversion is + * larger than {@link Long#MAX_VALUE} then CVTTSD2SI returns {@link Long#MIN_VALUE} and extra + * tests are required on the double value to return the correct long value. + * + * @param input the double being converted + * @param result the result produced by the CVTTSS2SI instruction + */ + @Snippet + public static long d2l(@Parameter("input") double input, @Parameter("result") long result) { + if (result == Long.MIN_VALUE) { + probability(NOT_FREQUENT_PROBABILITY); + if (Double.isNaN(input)) { + // input is NaN -> return 0 + return 0; + } else if (input > 0.0d) { + // input is positive -> return maxInt + return Long.MAX_VALUE; + } + } + return result; + } + + public static class Templates extends AbstractTemplates<AMD64ConvertSnippets> { + + private final ResolvedJavaMethod f2i; + private final ResolvedJavaMethod f2l; + private final ResolvedJavaMethod d2i; + private final ResolvedJavaMethod d2l; + + public Templates(CodeCacheProvider runtime, Assumptions assumptions, TargetDescription target) { + super(runtime, assumptions, target, AMD64ConvertSnippets.class); + f2i = snippet("f2i", float.class, int.class); + f2l = snippet("f2l", float.class, long.class); + d2i = snippet("d2i", double.class, int.class); + d2l = snippet("d2l", double.class, long.class); + } + + public void lower(ConvertNode convert, LoweringTool tool) { + if (convert.opcode == Op.F2I) { + lower0(convert, tool, f2i); + } else if (convert.opcode == Op.F2L) { + lower0(convert, tool, f2l); + } else if (convert.opcode == Op.D2I) { + lower0(convert, tool, d2i); + } else if (convert.opcode == Op.D2L) { + lower0(convert, tool, d2l); + } + } + + private void lower0(ConvertNode convert, LoweringTool tool, ResolvedJavaMethod snippet) { + StructuredGraph graph = (StructuredGraph) convert.graph(); + + // Insert a unique placeholder node in place of the Convert node so that the + // Convert node can be used as an input to the snippet. All usage of the + // Convert node are replaced by the placeholder which in turn is replaced by the + // snippet. + + LocalNode replacee = graph.add(new LocalNode(Integer.MAX_VALUE, convert.stamp())); + convert.replaceAtUsages(replacee); + Key key = new Key(snippet); + Arguments arguments = arguments("input", convert.value()).add("result", convert); + SnippetTemplate template = cache.get(key, assumptions); + Debug.log("Lowering %s in %s: node=%s, template=%s, arguments=%s", convert.opcode, graph, convert, template, arguments); + template.instantiate(runtime, replacee, DEFAULT_REPLACER, tool, arguments); + } + } +}
--- a/graal/com.oracle.graal.hotspot.server/src/com/oracle/graal/hotspot/server/CompilationServer.java Tue Mar 12 11:38:24 2013 +0100 +++ b/graal/com.oracle.graal.hotspot.server/src/com/oracle/graal/hotspot/server/CompilationServer.java Tue Mar 12 11:38:52 2013 +0100 @@ -93,7 +93,6 @@ // return the initialized compiler to the client HotSpotGraalRuntime compiler = initializeServer(toVM); - compiler.getCompiler(); streams.getInvocation().sendResult(compiler); for (ConnectionObserver observer : observers) {
--- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/ArrayCopyIntrinsificationTest.java Tue Mar 12 11:38:24 2013 +0100 +++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/ArrayCopyIntrinsificationTest.java Tue Mar 12 11:38:52 2013 +0100 @@ -51,7 +51,7 @@ if (node instanceof Invoke) { Invoke invoke = (Invoke) node; Assert.assertTrue(invoke.callTarget() instanceof DirectCallTargetNode); - DirectCallTargetNode directCall = (DirectCallTargetNode) invoke.callTarget(); + AbstractCallTargetNode directCall = (AbstractCallTargetNode) invoke.callTarget(); Assert.assertTrue(directCall.target() instanceof JavaMethod); JavaMethod callee = (JavaMethod) directCall.target(); Assert.assertTrue(callee.getName().equals("<init>")); @@ -64,7 +64,7 @@ for (Node node : graph.getNodes()) { if (node instanceof Invoke) { Invoke invoke = (Invoke) node; - DirectCallTargetNode directCall = (DirectCallTargetNode) invoke.callTarget(); + AbstractCallTargetNode directCall = (AbstractCallTargetNode) invoke.callTarget(); JavaMethod callee = (JavaMethod) directCall.target(); if (callee.getDeclaringClass().equals(runtime.lookupJavaType(System.class)) && callee.getName().equals("arraycopy")) { found = true;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java Tue Mar 12 11:38:24 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java Tue Mar 12 11:38:52 2013 +0100 @@ -146,7 +146,8 @@ graph = graph.copy(); } InlinedBytecodes.add(method.getCodeSize()); - return GraalCompiler.compileMethod(graalRuntime.getRuntime(), graalRuntime.getBackend(), graalRuntime.getTarget(), method, graph, graalRuntime.getCache(), plan, optimisticOpts); + return GraalCompiler.compileMethod(graalRuntime.getRuntime(), graalRuntime.getBackend(), graalRuntime.getTarget(), method, graph, graalRuntime.getCache(), plan, + optimisticOpts, method.getSpeculationLog()); } }); } finally { @@ -177,7 +178,7 @@ } private void installMethod(final CompilationResult tm) { - Debug.scope("CodeInstall", new Object[]{new DebugDumpScope(String.valueOf(id), true), graalRuntime.getCompiler(), method}, new Runnable() { + Debug.scope("CodeInstall", new Object[]{new DebugDumpScope(String.valueOf(id), true), graalRuntime.getRuntime(), method}, new Runnable() { @Override public void run() {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java Tue Mar 12 11:38:24 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java Tue Mar 12 11:38:52 2013 +0100 @@ -30,7 +30,6 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.api.runtime.*; -import com.oracle.graal.compiler.*; import com.oracle.graal.compiler.target.*; import com.oracle.graal.hotspot.bridge.*; import com.oracle.graal.hotspot.logging.*; @@ -110,7 +109,6 @@ protected/* final */VMToCompiler vmToCompiler; protected final HotSpotRuntime runtime; - protected final GraalCompiler compiler; protected final TargetDescription target; private HotSpotRuntimeInterpreterInterface runtimeInterpreterInterface; @@ -143,7 +141,6 @@ backend = createBackend(); GraalOptions.StackShadowPages = config.stackShadowPages; - compiler = new GraalCompiler(); if (GraalOptions.CacheGraphs) { cache = new HotSpotGraphCache(); } @@ -178,10 +175,6 @@ return target; } - public GraalCompiler getCompiler() { - return compiler; - } - public HotSpotGraphCache getCache() { return cache; } @@ -267,9 +260,6 @@ if (clazz == HotSpotRuntime.class) { return (T) runtime; } - if (clazz == GraalCompiler.class) { - return (T) getCompiler(); - } if (clazz == Backend.class) { return (T) getBackend(); }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java Tue Mar 12 11:38:24 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java Tue Mar 12 11:38:52 2013 +0100 @@ -304,8 +304,6 @@ public int typeProfileWidth; // runtime stubs - public long debugStub; - public long instanceofStub; public long newInstanceStub; public long newArrayStub; public long newMultiArrayStub; @@ -320,7 +318,6 @@ public long unwindExceptionStub; public long osrMigrationEndStub; public long registerFinalizerStub; - public long setDeoptInfoStub; public long createNullPointerExceptionStub; public long createOutOfBoundsExceptionStub; public long javaTimeMillisStub;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java Tue Mar 12 11:38:24 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java Tue Mar 12 11:38:52 2013 +0100 @@ -25,6 +25,7 @@ import java.lang.reflect.*; +import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.meta.*; @@ -152,7 +153,7 @@ * not null * @return the outcome of the installation as a {@link CodeInstallResult}. */ - CodeInstallResult installCode(HotSpotCompilationResult compResult, HotSpotInstalledCode code, HotSpotCodeInfo info); + CodeInstallResult installCode(HotSpotCompilationResult compResult, HotSpotInstalledCode code, HotSpotCodeInfo info, SpeculationLog cache); void initializeConfiguration(HotSpotVMConfig config);
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java Tue Mar 12 11:38:24 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java Tue Mar 12 11:38:52 2013 +0100 @@ -25,6 +25,7 @@ import java.lang.reflect.*; +import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.meta.*; @@ -34,11 +35,11 @@ */ public class CompilerToVMImpl implements CompilerToVM { - private native int installCode0(HotSpotCompilationResult comp, HotSpotInstalledCode code, HotSpotCodeInfo info); + private native int installCode0(HotSpotCompilationResult comp, HotSpotInstalledCode code, HotSpotCodeInfo info, boolean[] triggeredDeoptimizations); @Override - public CodeInstallResult installCode(HotSpotCompilationResult comp, HotSpotInstalledCode code, HotSpotCodeInfo info) { - return CodeInstallResult.values()[installCode0(comp, code, info)]; + public CodeInstallResult installCode(HotSpotCompilationResult comp, HotSpotInstalledCode code, HotSpotCodeInfo info, SpeculationLog speculationLog) { + return CodeInstallResult.values()[installCode0(comp, code, info, (speculationLog == null) ? null : speculationLog.getRawMap())]; } @Override
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/Marks.java Tue Mar 12 11:38:24 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/Marks.java Tue Mar 12 11:38:52 2013 +0100 @@ -29,24 +29,18 @@ */ public interface Marks { - // @formatter:off - // These constants need to correspond to those of the same name in graalCodeInstaller.hpp - Integer MARK_VERIFIED_ENTRY = 0x0001; - Integer MARK_UNVERIFIED_ENTRY = 0x0002; - Integer MARK_OSR_ENTRY = 0x0003; - Integer MARK_UNWIND_ENTRY = 0x0004; - Integer MARK_EXCEPTION_HANDLER_ENTRY = 0x0005; - Integer MARK_DEOPT_HANDLER_ENTRY = 0x0006; - Integer MARK_STATIC_CALL_STUB = 0x1000; - Integer MARK_INVOKEINTERFACE = 0x2001; - Integer MARK_INVOKESTATIC = 0x2002; - Integer MARK_INVOKESPECIAL = 0x2003; - Integer MARK_INVOKEVIRTUAL = 0x2004; - Integer MARK_INLINE_INVOKEVIRTUAL = 0x2005; - Integer MARK_IMPLICIT_NULL = 0x3000; - Integer MARK_POLL_NEAR = 0x3001; - Integer MARK_POLL_RETURN_NEAR = 0x3002; - Integer MARK_POLL_FAR = 0x3003; - Integer MARK_POLL_RETURN_FAR = 0x3004; - + int MARK_VERIFIED_ENTRY = 1; + int MARK_UNVERIFIED_ENTRY = 2; + int MARK_OSR_ENTRY = 3; + int MARK_EXCEPTION_HANDLER_ENTRY = 4; + int MARK_DEOPT_HANDLER_ENTRY = 5; + int MARK_INVOKEINTERFACE = 6; + int MARK_INVOKEVIRTUAL = 7; + int MARK_INVOKESTATIC = 8; + int MARK_INVOKESPECIAL = 9; + int MARK_INLINE_INVOKE = 10; + int MARK_POLL_NEAR = 11; + int MARK_POLL_RETURN_NEAR = 12; + int MARK_POLL_FAR = 13; + int MARK_POLL_RETURN_FAR = 14; }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotInstalledCode.java Tue Mar 12 11:38:24 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotInstalledCode.java Tue Mar 12 11:38:52 2013 +0100 @@ -38,10 +38,16 @@ private static final long serialVersionUID = 156632908220561612L; private final HotSpotResolvedJavaMethod method; + private final boolean isDefault; long nmethod; - public HotSpotInstalledCode(HotSpotResolvedJavaMethod method) { + public HotSpotInstalledCode(HotSpotResolvedJavaMethod method, boolean isDefault) { this.method = method; + this.isDefault = isDefault; + } + + public boolean isDefault() { + return isDefault; } @Override
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java Tue Mar 12 11:38:24 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java Tue Mar 12 11:38:52 2013 +0100 @@ -30,6 +30,7 @@ import java.util.*; import java.util.concurrent.*; +import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.api.meta.ProfilingInfo.ExceptionSeen; import com.oracle.graal.bytecode.*; @@ -58,8 +59,8 @@ private HotSpotMethodData methodData; private byte[] code; private int compilationComplexity; - private CompilationTask currentTask; + private SpeculationLog speculationLog; HotSpotResolvedJavaMethod(HotSpotResolvedObjectType holder, long metaspaceMethod) { this.metaspaceMethod = metaspaceMethod; @@ -72,6 +73,13 @@ return holder; } + /** + * Gets the address of the C++ Method object for this method. + */ + public Constant getMetaspaceMethodConstant() { + return Constant.forIntegerKind(HotSpotGraalRuntime.getInstance().getTarget().wordKind, metaspaceMethod, this); + } + @Override public int getModifiers() { HotSpotVMConfig config = HotSpotGraalRuntime.getInstance().getConfig(); @@ -86,6 +94,9 @@ @Override public byte[] getCode() { + if (codeSize == 0) { + return null; + } if (code == null) { code = HotSpotGraalRuntime.getInstance().getCompilerToVM().initializeBytecode(metaspaceMethod, new byte[codeSize]); assert code.length == codeSize : "expected: " + codeSize + ", actual: " + code.length; @@ -335,4 +346,10 @@ return currentTask; } + public SpeculationLog getSpeculationLog() { + if (speculationLog == null) { + speculationLog = new SpeculationLog(); + } + return speculationLog; + } }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java Tue Mar 12 11:38:24 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java Tue Mar 12 11:38:52 2013 +0100 @@ -32,7 +32,6 @@ import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; import static com.oracle.graal.hotspot.snippets.SystemSubstitutions.*; import static com.oracle.graal.java.GraphBuilderPhase.RuntimeCalls.*; -import static com.oracle.graal.nodes.UnwindNode.*; import static com.oracle.graal.nodes.java.RegisterFinalizerNode.*; import static com.oracle.graal.snippets.Log.*; import static com.oracle.graal.snippets.MathSubstitutionsX86.*; @@ -196,10 +195,6 @@ return result; } - protected Value scratch(Kind kind) { - return globalStubRegConfig.getScratchRegister().asValue(kind); - } - public HotSpotRuntime(HotSpotVMConfig config, HotSpotGraalRuntime graalRuntime) { this.config = config; this.graalRuntime = graalRuntime; @@ -208,11 +203,6 @@ // @formatter:off - addRuntimeCall(UNWIND_EXCEPTION, config.unwindExceptionStub, - /* temps */ null, - /* ret */ ret(Kind.Void), - /* arg0: exception */ javaCallingConvention(Kind.Object)); - addRuntimeCall(OnStackReplacementPhase.OSR_MIGRATION_END, config.osrMigrationEndStub, /* temps */ null, /* ret */ ret(Kind.Void), @@ -371,8 +361,8 @@ newInstanceStub = new NewInstanceStub(this, assumptions, graalRuntime.getTarget()); newArrayStub = new NewArrayStub(this, assumptions, graalRuntime.getTarget()); - newInstanceStub.install(backend, graalRuntime.getCompiler()); - newArrayStub.install(backend, graalRuntime.getCompiler()); + newInstanceStub.install(backend); + newArrayStub.install(backend); } public HotSpotGraalRuntime getGraalRuntime() { @@ -574,6 +564,9 @@ graph.addAfterFixed(metaspaceMethod, compiledEntry); } } + } else if (callTarget.invokeKind() == InvokeKind.Special || callTarget.invokeKind() == InvokeKind.Static) { + loweredCallTarget = graph.add(new HotSpotDirectCallTargetNode(parameters, invoke.node().stamp(), signature, callTarget.targetMethod(), CallingConvention.Type.JavaCall, + callTarget.invokeKind())); } if (loweredCallTarget == null) { @@ -824,15 +817,16 @@ public void installMethod(HotSpotResolvedJavaMethod method, int entryBCI, CompilationResult compResult, CodeInfo[] info) { HotSpotCodeInfo hsInfo = makeInfo(method, compResult, info); - graalRuntime.getCompilerToVM().installCode(new HotSpotCompilationResult(method, entryBCI, compResult), null, hsInfo); + HotSpotInstalledCode code = new HotSpotInstalledCode(method, true); + graalRuntime.getCompilerToVM().installCode(new HotSpotCompilationResult(method, entryBCI, compResult), code, hsInfo, method.getSpeculationLog()); } @Override public InstalledCode addMethod(ResolvedJavaMethod method, CompilationResult compResult, CodeInfo[] info) { HotSpotCodeInfo hsInfo = makeInfo(method, compResult, info); HotSpotResolvedJavaMethod hotspotMethod = (HotSpotResolvedJavaMethod) method; - HotSpotInstalledCode code = new HotSpotInstalledCode(hotspotMethod); - CodeInstallResult result = graalRuntime.getCompilerToVM().installCode(new HotSpotCompilationResult(hotspotMethod, -1, compResult), code, hsInfo); + HotSpotInstalledCode code = new HotSpotInstalledCode(hotspotMethod, false); + CodeInstallResult result = graalRuntime.getCompilerToVM().installCode(new HotSpotCompilationResult(hotspotMethod, -1, compResult), code, hsInfo, null); if (result != CodeInstallResult.OK) { return null; } @@ -900,7 +894,7 @@ } public boolean needsDataPatch(Constant constant) { - return constant.getPrimitiveAnnotation() instanceof HotSpotResolvedObjectType; + return constant.getPrimitiveAnnotation() != null; } /** @@ -953,7 +947,7 @@ long nmethod = ((HotSpotInstalledCode) code).nmethod; return graalRuntime.getCompilerToVM().disassembleNMethod(nmethod); } - return ""; + return null; } public String disassemble(ResolvedJavaMethod method) {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/Stub.java Tue Mar 12 11:38:24 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/Stub.java Tue Mar 12 11:38:52 2013 +0100 @@ -70,8 +70,8 @@ protected InstalledCode stubCode; /** - * Creates a new stub container. The new stub still needs to be - * {@linkplain #install(Backend, GraalCompiler) installed}. + * Creates a new stub container. The new stub still needs to be {@linkplain #install(Backend) + * installed}. * * @param descriptor linkage details for a call to the stub */ @@ -107,7 +107,7 @@ * Compiles the code for this stub, installs it and initializes the address used for calls to * it. */ - public void install(Backend backend, GraalCompiler compiler) { + public void install(Backend backend) { StructuredGraph graph = (StructuredGraph) stubMethod.getCompilerStorage().get(Graph.class); Key key = new Key(stubMethod); @@ -118,10 +118,11 @@ PhasePlan phasePlan = new PhasePlan(); GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getDefault(), OptimisticOptimizations.ALL); phasePlan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase); - final CompilationResult compResult = GraalCompiler.compileMethod(runtime(), backend, runtime().getTarget(), stubMethod, graph, null, phasePlan, OptimisticOptimizations.ALL); + final CompilationResult compResult = GraalCompiler.compileMethod(runtime(), backend, runtime().getTarget(), stubMethod, graph, null, phasePlan, OptimisticOptimizations.ALL, + new SpeculationLog()); final CodeInfo[] info = new CodeInfo[1]; - stubCode = Debug.scope("CodeInstall", new Object[]{compiler, stubMethod}, new Callable<InstalledCode>() { + stubCode = Debug.scope("CodeInstall", new Object[]{runtime(), stubMethod}, new Callable<InstalledCode>() { @Override public InstalledCode call() {
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderConfiguration.java Tue Mar 12 11:38:24 2013 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderConfiguration.java Tue Mar 12 11:38:52 2013 +0100 @@ -62,4 +62,13 @@ public static GraphBuilderConfiguration getSnippetDefault() { return new GraphBuilderConfiguration(true, true); } + + /** + * Returns {@code true} if it is an error for a class/field/method resolution to fail. + * The default is the same result as returned by {@link #eagerResolving()}. + * However, it may be overridden to allow failure even when {@link #eagerResolving} is {@code true}. + */ + public boolean unresolvedIsError() { + return eagerResolving; + } }
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Tue Mar 12 11:38:24 2013 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Tue Mar 12 11:38:52 2013 +0100 @@ -114,6 +114,20 @@ private Block[] loopHeaders; + /** + * Gets the current frame state being processed by this builder. + */ + protected FrameStateBuilder getCurrentFrameState() { + return frameState; + } + + /** + * Gets the graph being processed by this builder. + */ + protected StructuredGraph getGraph() { + return currentGraph; + } + public GraphBuilderPhase(MetaAccessProvider runtime, GraphBuilderConfiguration graphBuilderConfig, OptimisticOptimizations optimisticOpts) { this.graphBuilderConfig = graphBuilderConfig; this.optimisticOpts = optimisticOpts; @@ -261,6 +275,99 @@ return handler.catchTypeCPI() == 0; } + /** + * @param type the unresolved type of the constant + */ + protected void handleUnresolvedLoadConstant(JavaType type) { + append(currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved))); + frameState.push(Kind.Object, append(ConstantNode.forObject(null, runtime, currentGraph))); + } + + /** + * @param type the unresolved type of the type check + * @param object the object value whose type is being checked against {@code type} + */ + protected void handleUnresolvedCheckCast(JavaType type, ValueNode object) { + append(currentGraph.add(new FixedGuardNode(currentGraph.unique(new IsNullNode(object)), DeoptimizationReason.Unresolved, DeoptimizationAction.InvalidateRecompile))); + frameState.apush(appendConstant(Constant.NULL_OBJECT)); + } + + /** + * @param type the unresolved type of the type check + * @param object the object value whose type is being checked against {@code type} + */ + protected void handleUnresolvedInstanceOf(JavaType type, ValueNode object) { + BlockPlaceholderNode successor = currentGraph.add(new BlockPlaceholderNode()); + DeoptimizeNode deopt = currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved)); + IfNode ifNode = currentGraph.add(new IfNode(currentGraph.unique(new IsNullNode(object)), successor, deopt, 1)); + append(ifNode); + lastInstr = successor; + frameState.ipush(appendConstant(Constant.INT_0)); + } + + /** + * @param type the type being instantiated + */ + protected void handleUnresolvedNewInstance(JavaType type) { + append(currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved))); + frameState.apush(appendConstant(Constant.NULL_OBJECT)); + } + + /** + * @param type the type of the array being instantiated + * @param length the length of the array + */ + protected void handleUnresolvedNewObjectArray(JavaType type, ValueNode length) { + append(currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved))); + frameState.apush(appendConstant(Constant.NULL_OBJECT)); + } + + /** + * @param type the type being instantiated + * @param dims the dimensions for the multi-array + */ + protected void handleUnresolvedNewMultiArray(JavaType type, ValueNode[] dims) { + append(currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved))); + frameState.apush(appendConstant(Constant.NULL_OBJECT)); + } + + /** + * @param field the unresolved field + * @param receiver the object containing the field or {@code null} if {@code field} is static + */ + protected void handleUnresolvedLoadField(JavaField field, ValueNode receiver) { + Kind kind = field.getKind(); + append(currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved))); + frameState.push(kind.getStackKind(), append(ConstantNode.defaultForKind(kind, currentGraph))); + } + + /** + * @param field the unresolved field + * @param value the value being stored to the field + * @param receiver the object containing the field or {@code null} if {@code field} is static + */ + protected void handleUnresolvedStoreField(JavaField field, ValueNode value, ValueNode receiver) { + append(currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved))); + } + + /** + * @param representation + * @param type + */ + protected void handleUnresolvedExceptionType(Representation representation, JavaType type) { + append(currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved))); + } + + protected void handleUnresolvedInvoke(JavaMethod javaMethod, InvokeKind invokeKind) { + boolean withReceiver = invokeKind != InvokeKind.Static; + append(currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved))); + frameState.popArguments(javaMethod.getSignature().getParameterSlots(withReceiver), javaMethod.getSignature().getParameterCount(withReceiver)); + Kind kind = javaMethod.getSignature().getReturnKind(); + if (kind != Kind.Void) { + frameState.push(kind.getStackKind(), append(ConstantNode.defaultForKind(kind, currentGraph))); + } + } + private DispatchBeginNode handleException(ValueNode exceptionObject, int bci) { assert bci == FrameState.BEFORE_BCI || bci == bci() : "invalid bci"; Debug.log("Creating exception dispatch edges at %d, exception object=%s, exception seen=%s", bci, exceptionObject, profilingInfo.getExceptionSeen(bci)); @@ -307,8 +414,7 @@ if (type instanceof ResolvedJavaType) { frameState.push(Kind.Object, append(ConstantNode.forConstant(((ResolvedJavaType) type).getEncoding(Representation.JavaClass), runtime, currentGraph))); } else { - append(currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved))); - frameState.push(Kind.Object, append(ConstantNode.forObject(null, runtime, currentGraph))); + handleUnresolvedLoadConstant(type); } } else if (con instanceof Constant) { Constant constant = (Constant) con; @@ -636,21 +742,21 @@ private JavaType lookupType(int cpi, int bytecode) { eagerResolvingForSnippets(cpi, bytecode); JavaType result = constantPool.lookupType(cpi, bytecode); - assert !graphBuilderConfig.eagerResolving() || result instanceof ResolvedJavaType; + assert !graphBuilderConfig.unresolvedIsError() || result instanceof ResolvedJavaType; return result; } private JavaMethod lookupMethod(int cpi, int opcode) { eagerResolvingForSnippets(cpi, opcode); JavaMethod result = constantPool.lookupMethod(cpi, opcode); - assert !graphBuilderConfig.eagerResolving() || ((result instanceof ResolvedJavaMethod) && ((ResolvedJavaMethod) result).getDeclaringClass().isInitialized()) : result; + assert !graphBuilderConfig.unresolvedIsError() || ((result instanceof ResolvedJavaMethod) && ((ResolvedJavaMethod) result).getDeclaringClass().isInitialized()) : result; return result; } private JavaField lookupField(int cpi, int opcode) { eagerResolvingForSnippets(cpi, opcode); JavaField result = constantPool.lookupField(cpi, opcode); - assert !graphBuilderConfig.eagerResolving() || (result instanceof ResolvedJavaField && ((ResolvedJavaField) result).getDeclaringClass().isInitialized()) : result; + assert !graphBuilderConfig.unresolvedIsError() || (result instanceof ResolvedJavaField && ((ResolvedJavaField) result).getDeclaringClass().isInitialized()) : result; return result; } @@ -683,16 +789,13 @@ private void genCheckCast() { int cpi = stream().readCPI(); JavaType type = lookupType(cpi, CHECKCAST); - boolean initialized = type instanceof ResolvedJavaType; - if (initialized) { - ValueNode object = frameState.apop(); + ValueNode object = frameState.apop(); + if (type instanceof ResolvedJavaType) { CheckCastNode checkCast = currentGraph.add(new CheckCastNode((ResolvedJavaType) type, object, getProfileForTypeCheck((ResolvedJavaType) type))); append(checkCast); frameState.apush(checkCast); } else { - ValueNode object = frameState.apop(); - append(currentGraph.add(new FixedGuardNode(currentGraph.unique(new IsNullNode(object)), DeoptimizationReason.Unresolved, DeoptimizationAction.InvalidateRecompile))); - frameState.apush(appendConstant(Constant.NULL_OBJECT)); + handleUnresolvedCheckCast(type, object); } } @@ -706,12 +809,7 @@ ConditionalNode conditional = currentGraph.unique(new ConditionalNode(currentGraph.unique(instanceOfNode), ConstantNode.forInt(1, currentGraph), ConstantNode.forInt(0, currentGraph))); frameState.ipush(append(conditional)); } else { - BlockPlaceholderNode successor = currentGraph.add(new BlockPlaceholderNode()); - DeoptimizeNode deopt = currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved)); - IfNode ifNode = currentGraph.add(new IfNode(currentGraph.unique(new IsNullNode(object)), successor, deopt, 1)); - append(ifNode); - lastInstr = successor; - frameState.ipush(appendConstant(Constant.INT_0)); + handleUnresolvedInstanceOf(type, object); } } @@ -721,8 +819,7 @@ NewInstanceNode n = currentGraph.add(new NewInstanceNode((ResolvedJavaType) type, true, false)); frameState.apush(append(n)); } else { - append(currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved))); - frameState.apush(appendConstant(Constant.NULL_OBJECT)); + handleUnresolvedNewInstance(type); } } @@ -772,8 +869,7 @@ NewArrayNode n = currentGraph.add(new NewArrayNode((ResolvedJavaType) type, length, true, false)); frameState.apush(append(n)); } else { - append(currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved))); - frameState.apush(appendConstant(Constant.NULL_OBJECT)); + handleUnresolvedNewObjectArray(type, length); } } @@ -789,8 +885,7 @@ FixedWithNextNode n = currentGraph.add(new NewMultiArrayNode((ResolvedJavaType) type, dims)); frameState.apush(append(n)); } else { - append(currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved))); - frameState.apush(appendConstant(Constant.NULL_OBJECT)); + handleUnresolvedNewMultiArray(type, dims); } } @@ -803,8 +898,7 @@ LoadFieldNode load = currentGraph.add(new LoadFieldNode(receiver, (ResolvedJavaField) field)); appendOptimizedLoadField(kind, load); } else { - append(currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved))); - frameState.push(kind.getStackKind(), append(ConstantNode.defaultForKind(kind, currentGraph))); + handleUnresolvedLoadField(field, receiver); } } @@ -890,7 +984,7 @@ StoreFieldNode store = currentGraph.add(new StoreFieldNode(receiver, (ResolvedJavaField) field, value)); appendOptimizedStoreField(store); } else { - append(currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved))); + handleUnresolvedStoreField(field, value, receiver); } } @@ -905,8 +999,7 @@ appendOptimizedLoadField(kind, load); } } else { - append(currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved))); - frameState.push(kind.getStackKind(), append(ConstantNode.defaultForKind(kind, currentGraph))); + handleUnresolvedLoadField(field, null); } } @@ -916,15 +1009,15 @@ StoreFieldNode store = currentGraph.add(new StoreFieldNode(null, (ResolvedJavaField) field, value)); appendOptimizedStoreField(store); } else { - append(currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved))); + handleUnresolvedStoreField(field, value, null); } } - private ConstantNode genTypeOrDeopt(Representation representation, JavaType holder, boolean initialized) { + private ConstantNode genTypeOrDeopt(Representation representation, JavaType type, boolean initialized) { if (initialized) { - return appendConstant(((ResolvedJavaType) holder).getEncoding(representation)); + return appendConstant(((ResolvedJavaType) type).getEncoding(representation)); } else { - append(currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved))); + handleUnresolvedExceptionType(representation, type); return null; } } @@ -944,13 +1037,13 @@ ResolvedJavaMethod resolvedTarget = (ResolvedJavaMethod) target; ResolvedJavaType holder = resolvedTarget.getDeclaringClass(); if (!holder.isInitialized() && GraalOptions.ResolveClassBeforeStaticInvoke) { - genInvokeDeopt(target, false); + handleUnresolvedInvoke(target, InvokeKind.Static); } else { ValueNode[] args = frameState.popArguments(resolvedTarget.getSignature().getParameterSlots(false), resolvedTarget.getSignature().getParameterCount(false)); appendInvoke(InvokeKind.Static, resolvedTarget, args); } } else { - genInvokeDeopt(target, false); + handleUnresolvedInvoke(target, InvokeKind.Static); } } @@ -959,7 +1052,7 @@ ValueNode[] args = frameState.popArguments(target.getSignature().getParameterSlots(true), target.getSignature().getParameterCount(true)); genInvokeIndirect(InvokeKind.Interface, (ResolvedJavaMethod) target, args); } else { - genInvokeDeopt(target, true); + handleUnresolvedInvoke(target, InvokeKind.Interface); } } @@ -968,7 +1061,7 @@ ValueNode[] args = frameState.popArguments(target.getSignature().getParameterSlots(true), target.getSignature().getParameterCount(true)); genInvokeIndirect(InvokeKind.Virtual, (ResolvedJavaMethod) target, args); } else { - genInvokeDeopt(target, true); + handleUnresolvedInvoke(target, InvokeKind.Virtual); } } @@ -980,16 +1073,7 @@ ValueNode[] args = frameState.popArguments(target.getSignature().getParameterSlots(true), target.getSignature().getParameterCount(true)); invokeDirect((ResolvedJavaMethod) target, args); } else { - genInvokeDeopt(target, true); - } - } - - private void genInvokeDeopt(JavaMethod unresolvedTarget, boolean withReceiver) { - append(currentGraph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.Unresolved))); - frameState.popArguments(unresolvedTarget.getSignature().getParameterSlots(withReceiver), unresolvedTarget.getSignature().getParameterCount(withReceiver)); - Kind kind = unresolvedTarget.getSignature().getReturnKind(); - if (kind != Kind.Void) { - frameState.push(kind.getStackKind(), append(ConstantNode.defaultForKind(kind, currentGraph))); + handleUnresolvedInvoke(target, InvokeKind.Special); } } @@ -1026,7 +1110,6 @@ Kind resultType = targetMethod.getSignature().getReturnKind(); if (GraalOptions.DeoptALot) { DeoptimizeNode deoptimize = currentGraph.add(new DeoptimizeNode(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint)); - deoptimize.setMessage(targetMethod.getName()); append(deoptimize); frameState.pushReturn(resultType, ConstantNode.defaultForKind(resultType, currentGraph)); return; @@ -1214,7 +1297,7 @@ } } - private ConstantNode appendConstant(Constant constant) { + protected ConstantNode appendConstant(Constant constant) { assert constant != null; return ConstantNode.forConstant(constant, runtime, currentGraph); } @@ -1225,7 +1308,7 @@ return fixed; } - private ValueNode append(FixedWithNextNode x) { + protected ValueNode append(FixedWithNextNode x) { return appendWithBCI(x); } @@ -1233,7 +1316,7 @@ return v; } - private ValueNode appendWithBCI(FixedWithNextNode x) { + protected ValueNode appendWithBCI(FixedWithNextNode x) { assert x.predecessor() == null : "instruction should not have been appended yet"; assert lastInstr.next() == null : "cannot append instruction to instruction which isn't end (" + lastInstr + "->" + lastInstr.next() + ")"; lastInstr.setNext(x);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/bytecode/BC_d2l03.java Tue Mar 12 11:38:52 2013 +0100 @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2009, 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 com.oracle.graal.jtt.bytecode; + +import com.oracle.graal.jtt.*; +import org.junit.*; + +/* + */ +public class BC_d2l03 extends JTTTest { + + public static long test(double divider) { + return (long) (((long) divider) * divider); + } + + @Test + public void run0() throws Throwable { + runTest("test", 34.5D); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64AddressValue.java Tue Mar 12 11:38:52 2013 +0100 @@ -0,0 +1,103 @@ +/* + * 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.graal.lir.amd64; + +import static com.oracle.graal.api.code.ValueUtil.*; +import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.asm.amd64.*; +import com.oracle.graal.asm.amd64.AMD64Address.Scale; +import com.oracle.graal.lir.*; + +public class AMD64AddressValue extends CompositeValue { + + private static final long serialVersionUID = -4444600052487578694L; + + @Component({REG, UNUSED}) protected AllocatableValue base; + @Component({REG, UNUSED}) protected AllocatableValue index; + protected final Scale scale; + protected final int displacement; + + public AMD64AddressValue(Kind kind, AllocatableValue base, int displacement) { + this(kind, base, AllocatableValue.UNUSED, Scale.Times1, displacement); + } + + public AMD64AddressValue(Kind kind, AllocatableValue base, AllocatableValue index, Scale scale, int displacement) { + super(kind); + this.base = base; + this.index = index; + this.scale = scale; + this.displacement = displacement; + } + + private static Register toRegister(AllocatableValue value) { + if (value == AllocatableValue.UNUSED) { + return Register.None; + } else { + RegisterValue reg = (RegisterValue) value; + return reg.getRegister(); + } + } + + public AMD64Address toAddress() { + return new AMD64Address(toRegister(base), toRegister(index), scale, displacement); + } + + @Override + public String toString() { + StringBuilder s = new StringBuilder(); + s.append(getKind().getJavaName()).append("["); + String sep = ""; + if (isLegal(base)) { + s.append(base); + sep = " + "; + } + if (isLegal(index)) { + s.append(sep).append(index).append(" * ").append(scale.value); + sep = " + "; + } + if (displacement < 0) { + s.append(" - ").append(-displacement); + } else if (displacement > 0) { + s.append(sep).append(displacement); + } + s.append("]"); + return s.toString(); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof AMD64AddressValue) { + AMD64AddressValue addr = (AMD64AddressValue) obj; + return getKind() == addr.getKind() && displacement == addr.displacement && base.equals(addr.base) && scale == addr.scale && index.equals(addr.index); + } + return false; + } + + @Override + public int hashCode() { + return base.hashCode() ^ index.hashCode() ^ (displacement << 4) ^ (scale.value << 8) ^ (getKind().ordinal() << 12); + } +}
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Arithmetic.java Tue Mar 12 11:38:24 2013 +0100 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Arithmetic.java Tue Mar 12 11:38:52 2013 +0100 @@ -28,8 +28,6 @@ import com.oracle.graal.amd64.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; -import com.oracle.graal.asm.*; -import com.oracle.graal.asm.amd64.AMD64Assembler.ConditionFlag; import com.oracle.graal.asm.amd64.*; import com.oracle.graal.graph.*; import com.oracle.graal.lir.*; @@ -44,15 +42,23 @@ INEG, LNEG, I2L, L2I, I2B, I2C, I2S, F2D, D2F, - I2F, I2D, F2I, D2I, - L2F, L2D, F2L, D2L, - MOV_I2F, MOV_L2D, MOV_F2I, MOV_D2L; + I2F, I2D, + L2F, L2D, + MOV_I2F, MOV_L2D, MOV_F2I, MOV_D2L, + /* + * Converts a float/double to an int/long. The result of the conversion does not comply with Java semantics + * when the input is a NaN, infinity or the conversion result is greater than Integer.MAX_VALUE/Long.MAX_VALUE. + */ + F2I, D2I, F2L, D2L; + /** + * Unary operation with separate source and destination operand. + */ public static class Unary2Op extends AMD64LIRInstruction { @Opcode private final AMD64Arithmetic opcode; @Def({REG}) protected AllocatableValue result; - @Use({REG}) protected AllocatableValue x; + @Use({REG, STACK}) protected AllocatableValue x; public Unary2Op(AMD64Arithmetic opcode, AllocatableValue result, AllocatableValue x) { this.opcode = opcode; @@ -66,6 +72,9 @@ } } + /** + * Unary operation with single operand for source and destination. + */ public static class Unary1Op extends AMD64LIRInstruction { @Opcode private final AMD64Arithmetic opcode; @Def({REG, HINT}) protected AllocatableValue result; @@ -84,13 +93,17 @@ } } - public static class Op2Stack extends AMD64LIRInstruction { + /** + * Binary operation with two operands. The first source operand is combined with the destination. + * The second source operand may be a stack slot. + */ + public static class BinaryRegStack extends AMD64LIRInstruction { @Opcode private final AMD64Arithmetic opcode; - @Def({REG, HINT}) protected Value result; - @Use({REG, STACK, CONST}) protected Value x; - @Alive({REG, STACK, CONST}) protected Value y; + @Def({REG, HINT}) protected AllocatableValue result; + @Use({REG, STACK}) protected AllocatableValue x; + @Alive({REG, STACK}) protected AllocatableValue y; - public Op2Stack(AMD64Arithmetic opcode, Value result, Value x, Value y) { + public BinaryRegStack(AMD64Arithmetic opcode, AllocatableValue result, AllocatableValue x, AllocatableValue y) { this.opcode = opcode; this.result = result; this.x = x; @@ -111,13 +124,17 @@ } } - public static class Op2Reg extends AMD64LIRInstruction { + /** + * Binary operation with two operands. The first source operand is combined with the destination. + * The second source operand must be a register. + */ + public static class BinaryRegReg extends AMD64LIRInstruction { @Opcode private final AMD64Arithmetic opcode; - @Def({REG, HINT}) protected Value result; - @Use({REG, STACK, CONST}) protected Value x; - @Alive({REG, CONST}) protected Value y; + @Def({REG, HINT}) protected AllocatableValue result; + @Use({REG, STACK}) protected AllocatableValue x; + @Alive({REG}) protected AllocatableValue y; - public Op2Reg(AMD64Arithmetic opcode, Value result, Value x, Value y) { + public BinaryRegReg(AMD64Arithmetic opcode, AllocatableValue result, AllocatableValue x, AllocatableValue y) { this.opcode = opcode; this.result = result; this.x = x; @@ -138,13 +155,45 @@ } } - public static class Op2RegCommutative extends AMD64LIRInstruction { + /** + * Binary operation with single source/destination operand and one constant. + */ + public static class BinaryRegConst extends AMD64LIRInstruction { @Opcode private final AMD64Arithmetic opcode; - @Def({REG, HINT}) protected Value result; - @Use({REG, STACK, CONST}) protected Value x; - @Use({REG, CONST}) protected Value y; + @Def({REG, HINT}) protected AllocatableValue result; + @Use({REG, STACK}) protected AllocatableValue x; + protected Constant y; + + public BinaryRegConst(AMD64Arithmetic opcode, AllocatableValue result, AllocatableValue x, Constant y) { + this.opcode = opcode; + this.result = result; + this.x = x; + this.y = y; + } + + @Override + public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { + AMD64Move.move(tasm, masm, result, x); + emit(tasm, masm, opcode, result, y, null); + } - public Op2RegCommutative(AMD64Arithmetic opcode, Value result, Value x, Value y) { + @Override + public void verify() { + super.verify(); + verifyKind(opcode, result, x, y); + } + } + + /** + * Commutative binary operation with two operands. One of the operands is combined with the result. + */ + public static class BinaryCommutative extends AMD64LIRInstruction { + @Opcode private final AMD64Arithmetic opcode; + @Def({REG, HINT}) protected AllocatableValue result; + @Use({REG, STACK}) protected AllocatableValue x; + @Use({REG, STACK}) protected AllocatableValue y; + + public BinaryCommutative(AMD64Arithmetic opcode, AllocatableValue result, AllocatableValue x, AllocatableValue y) { this.opcode = opcode; this.result = result; this.x = x; @@ -168,13 +217,16 @@ } } - public static class ShiftOp extends AMD64LIRInstruction { + /** + * Binary operation with separate source and destination and one constant operand. + */ + public static class BinaryRegStackConst extends AMD64LIRInstruction { @Opcode private final AMD64Arithmetic opcode; - @Def({REG, HINT}) protected Value result; - @Use({REG, STACK, CONST}) protected Value x; - @Alive({REG, CONST}) protected Value y; + @Def({REG}) protected AllocatableValue result; + @Use({REG, STACK}) protected AllocatableValue x; + protected Constant y; - public ShiftOp(AMD64Arithmetic opcode, Value result, Value x, Value y) { + public BinaryRegStackConst(AMD64Arithmetic opcode, AllocatableValue result, AllocatableValue x, Constant y) { this.opcode = opcode; this.result = result; this.x = x; @@ -190,22 +242,19 @@ @Override public void verify() { super.verify(); - assert isConstant(y) || asRegister(y) == AMD64.rcx; - assert differentRegisters(result, y) || sameRegister(x, y); - verifyKind(opcode, result, x, x); - assert y.getKind().getStackKind() == Kind.Int; + verifyKind(opcode, result, x, y); } } public static class DivRemOp extends AMD64LIRInstruction { @Opcode private final AMD64Arithmetic opcode; - @Def protected Value divResult; - @Def protected Value remResult; - @Use protected Value x; - @Alive protected Value y; + @Def protected AllocatableValue divResult; + @Def protected AllocatableValue remResult; + @Use protected AllocatableValue x; + @Alive protected AllocatableValue y; @State protected LIRFrameState state; - public DivRemOp(AMD64Arithmetic opcode, Value x, Value y, LIRFrameState state) { + public DivRemOp(AMD64Arithmetic opcode, AllocatableValue x, AllocatableValue y, LIRFrameState state) { this.opcode = opcode; this.divResult = AMD64.rax.asValue(x.getKind()); this.remResult = AMD64.rdx.asValue(x.getKind()); @@ -230,39 +279,6 @@ } } - public static class DivOp extends AMD64LIRInstruction { - @Opcode private final AMD64Arithmetic opcode; - @Def protected Value result; - @Use protected Value x; - @Alive protected Value y; - @Temp protected Value temp; - @State protected LIRFrameState state; - - public DivOp(AMD64Arithmetic opcode, Value result, Value x, Value y, LIRFrameState state) { - this.opcode = opcode; - this.result = result; - this.x = x; - this.y = y; - this.temp = asRegister(result) == AMD64.rax ? AMD64.rdx.asValue(result.getKind()) : AMD64.rax.asValue(result.getKind()); - this.state = state; - } - - @Override - public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - emit(tasm, masm, opcode, result, y, state); - } - - @Override - protected void verify() { - super.verify(); - // left input in rax, right input in any register but rax and rdx, result quotient in rax, result remainder in rdx - assert asRegister(x) == AMD64.rax; - assert differentRegisters(y, AMD64.rax.asValue(), AMD64.rdx.asValue()); - assert (name().endsWith("DIV") && asRegister(result) == AMD64.rax) || (name().endsWith("REM") && asRegister(result) == AMD64.rdx); - verifyKind(opcode, result, x, y); - } - } - @SuppressWarnings("unused") protected static void emit(TargetMethodAssembler tasm, AMD64MacroAssembler masm, AMD64Arithmetic opcode, AllocatableValue result) { @@ -326,19 +342,15 @@ case L2D: masm.cvtsi2sdq(asDoubleReg(dst), asLongReg(src)); break; case F2I: masm.cvttss2sil(asIntReg(dst), asFloatReg(src)); - emitConvertFixup(tasm, masm, dst, src); break; case D2I: masm.cvttsd2sil(asIntReg(dst), asDoubleReg(src)); - emitConvertFixup(tasm, masm, dst, src); break; case F2L: masm.cvttss2siq(asLongReg(dst), asFloatReg(src)); - emitConvertFixup(tasm, masm, dst, src); break; case D2L: masm.cvttsd2siq(asLongReg(dst), asDoubleReg(src)); - emitConvertFixup(tasm, masm, dst, src); break; case MOV_I2F: masm.movdl(asFloatReg(dst), asIntReg(src)); break; case MOV_L2D: masm.movdq(asDoubleReg(dst), asLongReg(src)); break; @@ -423,11 +435,13 @@ case IADD: masm.addl(asIntReg(dst), (AMD64Address) tasm.asIntAddr(src)); break; case ISUB: masm.subl(asIntReg(dst), (AMD64Address) tasm.asIntAddr(src)); break; case IAND: masm.andl(asIntReg(dst), (AMD64Address) tasm.asIntAddr(src)); break; + case IMUL: masm.imull(asIntReg(dst), (AMD64Address) tasm.asIntAddr(src)); break; case IOR: masm.orl(asIntReg(dst), (AMD64Address) tasm.asIntAddr(src)); break; case IXOR: masm.xorl(asIntReg(dst), (AMD64Address) tasm.asIntAddr(src)); break; case LADD: masm.addq(asLongReg(dst), (AMD64Address) tasm.asLongAddr(src)); break; case LSUB: masm.subq(asLongReg(dst), (AMD64Address) tasm.asLongAddr(src)); break; + case LMUL: masm.imulq(asLongReg(dst), (AMD64Address) tasm.asLongAddr(src)); break; case LAND: masm.andq(asLongReg(dst), (AMD64Address) tasm.asLongAddr(src)); break; case LOR: masm.orq(asLongReg(dst), (AMD64Address) tasm.asLongAddr(src)); break; case LXOR: masm.xorq(asLongReg(dst), (AMD64Address) tasm.asLongAddr(src)); break; @@ -441,6 +455,33 @@ case DSUB: masm.subsd(asDoubleReg(dst), (AMD64Address) tasm.asDoubleAddr(src)); break; case DMUL: masm.mulsd(asDoubleReg(dst), (AMD64Address) tasm.asDoubleAddr(src)); break; case DDIV: masm.divsd(asDoubleReg(dst), (AMD64Address) tasm.asDoubleAddr(src)); break; + + case I2B: masm.movsxb(asIntReg(dst), (AMD64Address) tasm.asIntAddr(src)); break; + case I2S: masm.movsxw(asIntReg(dst), (AMD64Address) tasm.asIntAddr(src)); break; + case I2L: masm.movslq(asLongReg(dst), (AMD64Address) tasm.asIntAddr(src)); break; + case F2D: masm.cvtss2sd(asDoubleReg(dst), (AMD64Address) tasm.asFloatAddr(src)); break; + case D2F: masm.cvtsd2ss(asFloatReg(dst), (AMD64Address) tasm.asDoubleAddr(src)); break; + case I2F: masm.cvtsi2ssl(asFloatReg(dst), (AMD64Address) tasm.asIntAddr(src)); break; + case I2D: masm.cvtsi2sdl(asDoubleReg(dst), (AMD64Address) tasm.asIntAddr(src)); break; + case L2F: masm.cvtsi2ssq(asFloatReg(dst), (AMD64Address) tasm.asLongAddr(src)); break; + case L2D: masm.cvtsi2sdq(asDoubleReg(dst), (AMD64Address) tasm.asLongAddr(src)); break; + case F2I: + masm.cvttss2sil(asIntReg(dst), (AMD64Address) tasm.asFloatAddr(src)); + break; + case D2I: + masm.cvttsd2sil(asIntReg(dst), (AMD64Address) tasm.asDoubleAddr(src)); + break; + case F2L: + masm.cvttss2siq(asLongReg(dst), (AMD64Address) tasm.asFloatAddr(src)); + break; + case D2L: + masm.cvttsd2siq(asLongReg(dst), (AMD64Address) tasm.asDoubleAddr(src)); + break; + case MOV_I2F: masm.movss(asFloatReg(dst), (AMD64Address) tasm.asIntAddr(src)); break; + case MOV_L2D: masm.movsd(asDoubleReg(dst), (AMD64Address) tasm.asLongAddr(src)); break; + case MOV_F2I: masm.movl(asIntReg(dst), (AMD64Address) tasm.asFloatAddr(src)); break; + case MOV_D2L: masm.movq(asLongReg(dst), (AMD64Address) tasm.asDoubleAddr(src)); break; + default: throw GraalInternalError.shouldNotReachHere(); } } @@ -451,67 +492,11 @@ } } - private static void emitConvertFixup(TargetMethodAssembler tasm, AMD64MacroAssembler masm, Value result, Value x) { - ConvertSlowPath slowPath = new ConvertSlowPath(result, x); - tasm.stubs.add(slowPath); - switch (result.getKind()) { - case Int: masm.cmpl(asIntReg(result), Integer.MIN_VALUE); break; - case Long: masm.cmpq(asLongReg(result), (AMD64Address) tasm.asLongConstRef(Constant.forLong(java.lang.Long.MIN_VALUE))); break; - default: throw GraalInternalError.shouldNotReachHere(); - } - masm.jcc(ConditionFlag.Equal, slowPath.start); - masm.bind(slowPath.continuation); - } - - private static class ConvertSlowPath extends AMD64Code { - public final Label start = new Label(); - public final Label continuation = new Label(); - private final Value result; - private final Value x; - - public ConvertSlowPath(Value result, Value x) { - this.result = result; - this.x = x; - } - - @Override - public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - masm.bind(start); - switch (x.getKind()) { - case Float: masm.ucomiss(asFloatReg(x), (AMD64Address) tasm.asFloatConstRef(Constant.FLOAT_0)); break; - case Double: masm.ucomisd(asDoubleReg(x), (AMD64Address) tasm.asDoubleConstRef(Constant.DOUBLE_0)); break; - default: throw GraalInternalError.shouldNotReachHere(); - } - Label nan = new Label(); - masm.jcc(ConditionFlag.Parity, nan); - masm.jcc(ConditionFlag.Below, continuation); - - // input is > 0 -> return maxInt - // result register already contains 0x80000000, so subtracting 1 gives 0x7fffffff - switch (result.getKind()) { - case Int: masm.decrementl(asIntReg(result), 1); break; - case Long: masm.decrementq(asLongReg(result), 1); break; - default: throw GraalInternalError.shouldNotReachHere(); - } - masm.jmp(continuation); - - // input is NaN -> return 0 - masm.bind(nan); - masm.xorptr(asRegister(result), asRegister(result)); - masm.jmp(continuation); - } - - @Override - public String description() { - return "convert " + x + " to " + result; - } - } - - private static void verifyKind(AMD64Arithmetic opcode, Value result, Value x, Value y) { assert (opcode.name().startsWith("I") && result.getKind() == Kind.Int && x.getKind().getStackKind() == Kind.Int && y.getKind().getStackKind() == Kind.Int) || (opcode.name().startsWith("L") && result.getKind() == Kind.Long && x.getKind() == Kind.Long && y.getKind() == Kind.Long) || (opcode.name().startsWith("F") && result.getKind() == Kind.Float && x.getKind() == Kind.Float && y.getKind() == Kind.Float) - || (opcode.name().startsWith("D") && result.getKind() == Kind.Double && x.getKind() == Kind.Double && y.getKind() == Kind.Double); + || (opcode.name().startsWith("D") && result.getKind() == Kind.Double && x.getKind() == Kind.Double && y.getKind() == Kind.Double) + || (opcode.name().matches(".U?SH.") && result.getKind() == x.getKind() && y.getKind() == Kind.Int && (isConstant(y) || asRegister(y) == AMD64.rcx)); } }
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64BitManipulationOp.java Tue Mar 12 11:38:24 2013 +0100 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64BitManipulationOp.java Tue Mar 12 11:38:52 2013 +0100 @@ -22,7 +22,6 @@ */ package com.oracle.graal.lir.amd64; -import com.oracle.graal.amd64.*; import com.oracle.graal.api.code.*; import com.oracle.graal.asm.amd64.*; import com.oracle.graal.lir.asm.*;
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Call.java Tue Mar 12 11:38:24 2013 +0100 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Call.java Tue Mar 12 11:38:52 2013 +0100 @@ -26,7 +26,6 @@ import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; import com.oracle.graal.api.code.*; -import com.oracle.graal.api.code.RuntimeCallTarget.Descriptor; import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.amd64.*; import com.oracle.graal.lir.*; @@ -35,8 +34,6 @@ public class AMD64Call { - public static final Descriptor DEBUG = new Descriptor("debug", false, void.class); - @Opcode("CALL_DIRECT") public static class DirectCallOp extends AMD64LIRInstruction implements StandardOp.CallOp { @@ -66,7 +63,10 @@ // make sure that the displacement word of the call ends up word aligned int offset = masm.codeBuffer.position(); offset += tasm.target.arch.getMachineCodeCallDisplacementOffset(); - masm.nop(tasm.target.wordSize - offset % tasm.target.wordSize); + int modulus = tasm.target.wordSize; + if (offset % modulus != 0) { + masm.nop(modulus - offset % modulus); + } } } @@ -142,14 +142,4 @@ tasm.recordExceptionHandlers(after, info); masm.ensureUniquePC(); } - - public static void shouldNotReachHere(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - boolean assertions = false; - assert (assertions = true) == true; - - if (assertions) { - directCall(tasm, masm, tasm.runtime.lookupRuntimeCall(DEBUG), null); - masm.hlt(); - } - } }
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Compare.java Tue Mar 12 11:38:24 2013 +0100 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Compare.java Tue Mar 12 11:38:52 2013 +0100 @@ -25,7 +25,6 @@ import static com.oracle.graal.api.code.ValueUtil.*; import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; -import com.oracle.graal.amd64.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.amd64.*; import com.oracle.graal.graph.*;
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ControlFlow.java Tue Mar 12 11:38:24 2013 +0100 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ControlFlow.java Tue Mar 12 11:38:52 2013 +0100 @@ -26,13 +26,13 @@ import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; import com.oracle.graal.amd64.*; -import com.oracle.graal.amd64.AMD64Address.Scale; +import com.oracle.graal.api.code.CompilationResult.JumpTable; import com.oracle.graal.api.code.*; -import com.oracle.graal.api.code.CompilationResult.JumpTable; import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.*; +import com.oracle.graal.asm.amd64.*; +import com.oracle.graal.asm.amd64.AMD64Address.Scale; import com.oracle.graal.asm.amd64.AMD64Assembler.ConditionFlag; -import com.oracle.graal.asm.amd64.*; import com.oracle.graal.graph.*; import com.oracle.graal.lir.*; import com.oracle.graal.lir.LIRInstruction.Opcode; @@ -338,11 +338,11 @@ // Set scratch to address of jump table int leaPos = buf.position(); - masm.leaq(scratch, new AMD64Address(tasm.target.wordKind, AMD64.rip.asValue(), 0)); + masm.leaq(scratch, new AMD64Address(AMD64.rip, 0)); int afterLea = buf.position(); // Load jump table entry into scratch and jump to it - masm.movslq(value, new AMD64Address(Kind.Int, scratch.asValue(), value.asValue(), Scale.Times4, 0)); + masm.movslq(value, new AMD64Address(scratch, value, Scale.Times4, 0)); masm.addq(scratch, value); masm.jmp(scratch); @@ -354,7 +354,7 @@ // Patch LEA instruction above now that we know the position of the jump table int jumpTablePos = buf.position(); buf.setPosition(leaPos); - masm.leaq(scratch, new AMD64Address(tasm.target.wordKind, AMD64.rip.asValue(), jumpTablePos - afterLea)); + masm.leaq(scratch, new AMD64Address(AMD64.rip, jumpTablePos - afterLea)); buf.setPosition(jumpTablePos); // Emit jump table entries
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Move.java Tue Mar 12 11:38:24 2013 +0100 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Move.java Tue Mar 12 11:38:52 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 @@ -42,33 +42,6 @@ public class AMD64Move { @Opcode("MOVE") - public static class SpillMoveOp extends AMD64LIRInstruction implements MoveOp { - - @Def({REG, STACK}) protected Value result; - @Use({REG, STACK, CONST}) protected Value input; - - public SpillMoveOp(Value result, Value input) { - this.result = result; - this.input = input; - } - - @Override - public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - move(tasm, masm, getResult(), getInput()); - } - - @Override - public Value getInput() { - return input; - } - - @Override - public Value getResult() { - return result; - } - } - - @Opcode("MOVE") public static class MoveToRegOp extends AMD64LIRInstruction implements MoveOp { @Def({REG, HINT}) protected Value result; @@ -124,10 +97,10 @@ public abstract static class MemOp extends AMD64LIRInstruction { - @Use({ADDR}) protected AMD64Address address; + @Use({COMPOSITE}) protected AMD64AddressValue address; @State protected LIRFrameState state; - public MemOp(AMD64Address address, LIRFrameState state) { + public MemOp(AMD64AddressValue address, LIRFrameState state) { this.address = address; this.state = state; } @@ -147,7 +120,7 @@ @Def({REG}) protected AllocatableValue result; - public LoadOp(AllocatableValue result, AMD64Address address, LIRFrameState state) { + public LoadOp(AllocatableValue result, AMD64AddressValue address, LIRFrameState state) { super(address, state); this.result = result; } @@ -157,28 +130,28 @@ switch (address.getKind()) { case Boolean: case Byte: - masm.movsxb(asRegister(result), address); + masm.movsxb(asRegister(result), address.toAddress()); break; case Char: - masm.movzxl(asRegister(result), address); + masm.movzxl(asRegister(result), address.toAddress()); break; case Short: - masm.movswl(asRegister(result), address); + masm.movswl(asRegister(result), address.toAddress()); break; case Int: - masm.movslq(asRegister(result), address); + masm.movslq(asRegister(result), address.toAddress()); break; case Long: - masm.movq(asRegister(result), address); + masm.movq(asRegister(result), address.toAddress()); break; case Float: - masm.movflt(asFloatReg(result), address); + masm.movflt(asFloatReg(result), address.toAddress()); break; case Double: - masm.movdbl(asDoubleReg(result), address); + masm.movdbl(asDoubleReg(result), address.toAddress()); break; case Object: - masm.movq(asRegister(result), address); + masm.movq(asRegister(result), address.toAddress()); break; default: throw GraalInternalError.shouldNotReachHere(); @@ -190,7 +163,7 @@ @Use({REG}) protected AllocatableValue input; - public StoreOp(AMD64Address address, AllocatableValue input, LIRFrameState state) { + public StoreOp(AMD64AddressValue address, AllocatableValue input, LIRFrameState state) { super(address, state); this.input = input; } @@ -201,26 +174,26 @@ switch (address.getKind()) { case Boolean: case Byte: - masm.movb(address, asRegister(input)); + masm.movb(address.toAddress(), asRegister(input)); break; case Char: case Short: - masm.movw(address, asRegister(input)); + masm.movw(address.toAddress(), asRegister(input)); break; case Int: - masm.movl(address, asRegister(input)); + masm.movl(address.toAddress(), asRegister(input)); break; case Long: - masm.movq(address, asRegister(input)); + masm.movq(address.toAddress(), asRegister(input)); break; case Float: - masm.movflt(address, asFloatReg(input)); + masm.movflt(address.toAddress(), asFloatReg(input)); break; case Double: - masm.movsd(address, asDoubleReg(input)); + masm.movsd(address.toAddress(), asDoubleReg(input)); break; case Object: - masm.movq(address, asRegister(input)); + masm.movq(address.toAddress(), asRegister(input)); break; default: throw GraalInternalError.shouldNotReachHere(); @@ -230,9 +203,9 @@ public static class StoreConstantOp extends MemOp { - @Use({CONST}) protected Constant input; + protected final Constant input; - public StoreConstantOp(AMD64Address address, Constant input, LIRFrameState state) { + public StoreConstantOp(AMD64AddressValue address, Constant input, LIRFrameState state) { super(address, state); this.input = input; } @@ -242,30 +215,30 @@ switch (address.getKind()) { case Boolean: case Byte: - masm.movb(address, input.asInt() & 0xFF); + masm.movb(address.toAddress(), input.asInt() & 0xFF); break; case Char: case Short: - masm.movw(address, input.asInt() & 0xFFFF); + masm.movw(address.toAddress(), input.asInt() & 0xFFFF); break; case Int: - masm.movl(address, input.asInt()); + masm.movl(address.toAddress(), input.asInt()); break; case Long: if (NumUtil.isInt(input.asLong())) { - masm.movslq(address, (int) input.asLong()); + masm.movslq(address.toAddress(), (int) input.asLong()); } else { throw GraalInternalError.shouldNotReachHere("Cannot store 64-bit constants to memory"); } break; case Float: - masm.movl(address, floatToRawIntBits(input.asFloat())); + masm.movl(address.toAddress(), floatToRawIntBits(input.asFloat())); break; case Double: throw GraalInternalError.shouldNotReachHere("Cannot store 64-bit constants to memory"); case Object: if (input.isNull()) { - masm.movptr(address, 0); + masm.movptr(address.toAddress(), 0); } else { throw GraalInternalError.shouldNotReachHere("Cannot store 64-bit constants to memory"); } @@ -279,16 +252,16 @@ public static class LeaOp extends AMD64LIRInstruction { @Def({REG}) protected AllocatableValue result; - @Use({ADDR, UNINITIALIZED}) protected AMD64Address address; + @Use({COMPOSITE, UNINITIALIZED}) protected AMD64AddressValue address; - public LeaOp(AllocatableValue result, AMD64Address address) { + public LeaOp(AllocatableValue result, AMD64AddressValue address) { this.result = result; this.address = address; } @Override public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - masm.leaq(asLongReg(result), address); + masm.leaq(asLongReg(result), address.toAddress()); } } @@ -343,11 +316,11 @@ public static class CompareAndSwapOp extends AMD64LIRInstruction { @Def protected AllocatableValue result; - @Use({ADDR}) protected AMD64Address address; + @Use({COMPOSITE}) protected AMD64AddressValue address; @Use protected AllocatableValue cmpValue; @Use protected AllocatableValue newValue; - public CompareAndSwapOp(AllocatableValue result, AMD64Address address, AllocatableValue cmpValue, AllocatableValue newValue) { + public CompareAndSwapOp(AllocatableValue result, AMD64AddressValue address, AllocatableValue cmpValue, AllocatableValue newValue) { this.result = result; this.address = address; this.cmpValue = cmpValue; @@ -550,7 +523,7 @@ } } - protected static void compareAndSwap(TargetMethodAssembler tasm, AMD64MacroAssembler masm, AllocatableValue result, AMD64Address address, AllocatableValue cmpValue, AllocatableValue newValue) { + protected static void compareAndSwap(TargetMethodAssembler tasm, AMD64MacroAssembler masm, AllocatableValue result, AMD64AddressValue address, AllocatableValue cmpValue, AllocatableValue newValue) { assert asRegister(cmpValue) == AMD64.rax && asRegister(result) == AMD64.rax; if (tasm.target.isMP) { @@ -558,11 +531,11 @@ } switch (cmpValue.getKind()) { case Int: - masm.cmpxchgl(asRegister(newValue), address); + masm.cmpxchgl(asRegister(newValue), address.toAddress()); break; case Long: case Object: - masm.cmpxchgq(asRegister(newValue), address); + masm.cmpxchgq(asRegister(newValue), address.toAddress()); break; default: throw GraalInternalError.shouldNotReachHere();
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64TestOp.java Tue Mar 12 11:38:24 2013 +0100 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64TestOp.java Tue Mar 12 11:38:52 2013 +0100 @@ -25,7 +25,6 @@ import static com.oracle.graal.api.code.ValueUtil.*; import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; -import com.oracle.graal.amd64.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.amd64.*; import com.oracle.graal.graph.*;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXAddressValue.java Tue Mar 12 11:38:52 2013 +0100 @@ -0,0 +1,106 @@ +/* + * 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.graal.lir.ptx; + +import static com.oracle.graal.api.code.ValueUtil.*; +import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.asm.ptx.*; +import com.oracle.graal.lir.*; + +/** + * Represents an address in target machine memory, specified via some combination of a base register + * and a displacement. + */ +public final class PTXAddressValue extends CompositeValue { + + private static final long serialVersionUID = 1802222435353022623L; + + @Component({REG, UNUSED}) private AllocatableValue base; + private final long displacement; + + /** + * Creates an {@link PTXAddressValue} with given base register and no displacement. + * + * @param kind the kind of the value being addressed + * @param base the base register + */ + public PTXAddressValue(Kind kind, AllocatableValue base) { + this(kind, base, 0); + } + + /** + * Creates an {@link PTXAddressValue} with given base register and a displacement. This is the + * most general constructor. + * + * @param kind the kind of the value being addressed + * @param base the base register + * @param displacement the displacement + */ + public PTXAddressValue(Kind kind, AllocatableValue base, long displacement) { + super(kind); + this.base = base; + this.displacement = displacement; + + assert !isStackSlot(base); + } + + public PTXAddress toAddress() { + Register baseReg = base == AllocatableValue.UNUSED ? Register.None : asRegister(base); + return new PTXAddress(baseReg, displacement); + } + + @Override + public String toString() { + StringBuilder s = new StringBuilder(); + s.append(getKind().getJavaName()).append("["); + String sep = ""; + if (isLegal(base)) { + s.append(base); + sep = " + "; + } + if (displacement < 0) { + s.append(" - ").append(-displacement); + } else if (displacement > 0) { + s.append(sep).append(displacement); + } + s.append("]"); + return s.toString(); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof PTXAddressValue) { + PTXAddressValue addr = (PTXAddressValue) obj; + return getKind() == addr.getKind() && displacement == addr.displacement && base.equals(addr.base); + } + return false; + } + + @Override + public int hashCode() { + return base.hashCode() ^ ((int) displacement << 4) ^ (getKind().ordinal() << 12); + } +}
--- a/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXBitManipulationOp.java Tue Mar 12 11:38:24 2013 +0100 +++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXBitManipulationOp.java Tue Mar 12 11:38:52 2013 +0100 @@ -36,7 +36,7 @@ @Opcode private final IntrinsicOpcode opcode; @Def protected Value result; - @Use({OperandFlag.REG, OperandFlag.ADDR}) protected Value input; + @Use({OperandFlag.REG}) protected Value input; public PTXBitManipulationOp(IntrinsicOpcode opcode, Value result, Value input) { this.opcode = opcode;
--- a/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXCompare.java Tue Mar 12 11:38:24 2013 +0100 +++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXCompare.java Tue Mar 12 11:38:52 2013 +0100 @@ -38,7 +38,7 @@ public static class CompareOp extends PTXLIRInstruction { @Opcode private final PTXCompare opcode; - @Use({REG}) protected Value x; + @Use({REG, STACK, CONST}) protected Value x; @Use({REG, STACK, CONST}) protected Value y; private final Condition condition;
--- a/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXMove.java Tue Mar 12 11:38:24 2013 +0100 +++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXMove.java Tue Mar 12 11:38:52 2013 +0100 @@ -33,7 +33,6 @@ import com.oracle.graal.lir.LIRInstruction.Opcode; import com.oracle.graal.lir.StandardOp.MoveOp; import com.oracle.graal.lir.asm.*; -import com.oracle.graal.ptx.*; public class PTXMove { @@ -121,10 +120,10 @@ public static class LoadOp extends PTXLIRInstruction { @Def({REG}) protected AllocatableValue result; - @Use({ADDR}) protected PTXAddress address; + @Use({COMPOSITE}) protected PTXAddressValue address; @State protected LIRFrameState state; - public LoadOp(AllocatableValue result, PTXAddress address, LIRFrameState state) { + public LoadOp(AllocatableValue result, PTXAddressValue address, LIRFrameState state) { this.result = result; this.address = address; this.state = state; @@ -132,14 +131,13 @@ @Override public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) { - Register a = asRegister(address.getBase()); - long immOff = address.getDisplacement(); + PTXAddress addr = address.toAddress(); switch (address.getKind()) { case Int: - masm.ld_global_s32(asRegister(result), a, immOff); + masm.ld_global_s32(asRegister(result), addr.getBase(), addr.getDisplacement()); break; case Object: - masm.ld_global_u32(asRegister(result), a, immOff); + masm.ld_global_u32(asRegister(result), addr.getBase(), addr.getDisplacement()); break; default: throw GraalInternalError.shouldNotReachHere(); @@ -149,11 +147,11 @@ public static class StoreOp extends PTXLIRInstruction { - @Use({ADDR}) protected PTXAddress address; + @Use({COMPOSITE}) protected PTXAddressValue address; @Use({REG}) protected AllocatableValue input; @State protected LIRFrameState state; - public StoreOp(PTXAddress address, AllocatableValue input, LIRFrameState state) { + public StoreOp(PTXAddressValue address, AllocatableValue input, LIRFrameState state) { this.address = address; this.input = input; this.state = state; @@ -161,13 +159,11 @@ @Override public void emitCode(TargetMethodAssembler tasm, PTXAssembler masm) { - Register a = asRegister(address.getBase()); - long immOff = address.getDisplacement(); - assert isRegister(input); + PTXAddress addr = address.toAddress(); switch (address.getKind()) { case Int: - masm.st_global_s32(a, immOff, asRegister(input)); + masm.st_global_s32(addr.getBase(), addr.getDisplacement(), asRegister(input)); break; default: throw GraalInternalError.shouldNotReachHere(); @@ -178,9 +174,9 @@ public static class LeaOp extends PTXLIRInstruction { @Def({REG}) protected AllocatableValue result; - @Use({ADDR, UNINITIALIZED}) protected PTXAddress address; + @Use({COMPOSITE, UNINITIALIZED}) protected PTXAddressValue address; - public LeaOp(AllocatableValue result, PTXAddress address) { + public LeaOp(AllocatableValue result, PTXAddressValue address) { this.result = result; this.address = address; } @@ -211,11 +207,11 @@ public static class CompareAndSwapOp extends PTXLIRInstruction { @Def protected AllocatableValue result; - @Use({ADDR}) protected PTXAddress address; + @Use({COMPOSITE}) protected PTXAddressValue address; @Use protected AllocatableValue cmpValue; @Use protected AllocatableValue newValue; - public CompareAndSwapOp(AllocatableValue result, PTXAddress address, AllocatableValue cmpValue, AllocatableValue newValue) { + public CompareAndSwapOp(AllocatableValue result, PTXAddressValue address, AllocatableValue cmpValue, AllocatableValue newValue) { this.result = result; this.address = address; this.cmpValue = cmpValue; @@ -276,7 +272,7 @@ } @SuppressWarnings("unused") - protected static void compareAndSwap(TargetMethodAssembler tasm, PTXAssembler masm, AllocatableValue result, PTXAddress address, AllocatableValue cmpValue, AllocatableValue newValue) { + protected static void compareAndSwap(TargetMethodAssembler tasm, PTXAssembler masm, AllocatableValue result, PTXAddressValue address, AllocatableValue cmpValue, AllocatableValue newValue) { throw new InternalError("NYI"); } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/CompositeValue.java Tue Mar 12 11:38:52 2013 +0100 @@ -0,0 +1,61 @@ +/* + * 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.graal.lir; + +import java.lang.annotation.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.lir.LIRInstruction.OperandFlag; +import com.oracle.graal.lir.LIRInstruction.OperandMode; +import com.oracle.graal.lir.LIRInstruction.ValueProcedure; + +/** + * Base class to represent values that need to be stored in more than one register. + */ +public abstract class CompositeValue extends Value { + + private static final long serialVersionUID = -169180052684126180L; + + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.FIELD) + public static @interface Component { + + OperandFlag[] value() default OperandFlag.REG; + } + + private final CompositeValueClass valueClass; + + public CompositeValue(Kind kind) { + super(kind); + valueClass = CompositeValueClass.get(getClass()); + } + + public final void forEachComponent(OperandMode mode, ValueProcedure proc) { + valueClass.forEachComponent(this, mode, proc); + } + + @Override + public String toString() { + return valueClass.toString(this); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/CompositeValueClass.java Tue Mar 12 11:38:52 2013 +0100 @@ -0,0 +1,145 @@ +/* + * 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.graal.lir; + +import java.lang.reflect.*; +import java.util.*; + +import com.oracle.graal.graph.*; +import com.oracle.graal.lir.LIRInstruction.OperandFlag; +import com.oracle.graal.lir.LIRInstruction.OperandMode; +import com.oracle.graal.lir.LIRInstruction.ValueProcedure; + +public class CompositeValueClass extends LIRIntrospection { + + public static final CompositeValueClass get(Class<? extends CompositeValue> c) { + CompositeValueClass clazz = (CompositeValueClass) allClasses.get(c); + if (clazz != null) { + return clazz; + } + + // We can have a race of multiple threads creating the LIRInstructionClass at the same time. + // However, only one will be put into the map, and this is the one returned by all threads. + clazz = new CompositeValueClass(c); + CompositeValueClass oldClazz = (CompositeValueClass) allClasses.putIfAbsent(c, clazz); + if (oldClazz != null) { + return oldClazz; + } else { + return clazz; + } + } + + private final int directComponentCount; + private final long[] componentOffsets; + private final EnumSet<OperandFlag>[] componentFlags; + + @SuppressWarnings("unchecked") + public CompositeValueClass(Class<? extends CompositeValue> clazz) { + super(clazz); + + ValueFieldScanner scanner = new ValueFieldScanner(new DefaultCalcOffset()); + scanner.scan(clazz); + + OperandModeAnnotation mode = scanner.valueAnnotations.get(CompositeValue.Component.class); + directComponentCount = mode.scalarOffsets.size(); + componentOffsets = sortedLongCopy(mode.scalarOffsets, mode.arrayOffsets); + componentFlags = arrayUsingSortedOffsets(mode.flags, componentOffsets, new EnumSet[componentOffsets.length]); + + dataOffsets = sortedLongCopy(scanner.dataOffsets); + + fieldNames = scanner.fieldNames; + fieldTypes = scanner.fieldTypes; + } + + @Override + protected void rescanFieldOffsets(CalcOffset calc) { + ValueFieldScanner scanner = new ValueFieldScanner(calc); + scanner.scan(clazz); + + OperandModeAnnotation mode = scanner.valueAnnotations.get(CompositeValue.Component.class); + copyInto(componentOffsets, sortedLongCopy(mode.scalarOffsets, mode.arrayOffsets)); + + copyInto(dataOffsets, sortedLongCopy(scanner.dataOffsets)); + + fieldNames.clear(); + fieldNames.putAll(scanner.fieldNames); + fieldTypes.clear(); + fieldTypes.putAll(scanner.fieldTypes); + } + + private static class ValueFieldScanner extends FieldScanner { + + public ValueFieldScanner(CalcOffset calc) { + super(calc); + + valueAnnotations.put(CompositeValue.Component.class, new OperandModeAnnotation()); + } + + @Override + protected void scan(Class<?> clazz) { + super.scan(clazz); + } + + @Override + protected EnumSet<OperandFlag> getFlags(Field field) { + EnumSet<OperandFlag> result = EnumSet.noneOf(OperandFlag.class); + if (field.isAnnotationPresent(CompositeValue.Component.class)) { + result.addAll(Arrays.asList(field.getAnnotation(CompositeValue.Component.class).value())); + } else { + GraalInternalError.shouldNotReachHere(); + } + return result; + } + } + + @Override + public String toString() { + StringBuilder str = new StringBuilder(); + str.append(getClass().getSimpleName()).append(" ").append(clazz.getSimpleName()).append(" component["); + for (int i = 0; i < componentOffsets.length; i++) { + str.append(i == 0 ? "" : ", ").append(componentOffsets[i]); + } + str.append("] data["); + for (int i = 0; i < dataOffsets.length; i++) { + str.append(i == 0 ? "" : ", ").append(dataOffsets[i]); + } + str.append("]"); + return str.toString(); + } + + public final void forEachComponent(CompositeValue obj, OperandMode mode, ValueProcedure proc) { + forEach(obj, directComponentCount, componentOffsets, mode, componentFlags, proc); + } + + public String toString(CompositeValue obj) { + StringBuilder result = new StringBuilder(); + + appendValues(result, obj, "", "", "{", "}", new String[]{""}, componentOffsets); + + for (int i = 0; i < dataOffsets.length; i++) { + result.append(" ").append(fieldNames.get(dataOffsets[i])).append(": ").append(getFieldString(obj, dataOffsets[i])); + } + + return result.toString(); + } +}
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIR.java Tue Mar 12 11:38:24 2013 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIR.java Tue Mar 12 11:38:52 2013 +0100 @@ -24,6 +24,7 @@ import java.util.*; +import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.debug.*; import com.oracle.graal.graph.*; @@ -74,6 +75,8 @@ private boolean hasArgInCallerFrame; + private final SpeculationLog speculationLog; + /** * An opaque chunk of machine code. */ @@ -90,7 +93,7 @@ /** * Creates a new LIR instance for the specified compilation. */ - public LIR(ControlFlowGraph cfg, BlockMap<List<ScheduledNode>> blockToNodesMap, List<Block> linearScanOrder, List<Block> codeEmittingOrder) { + public LIR(ControlFlowGraph cfg, BlockMap<List<ScheduledNode>> blockToNodesMap, List<Block> linearScanOrder, List<Block> codeEmittingOrder, SpeculationLog speculationLog) { this.cfg = cfg; this.blockToNodesMap = blockToNodesMap; this.codeEmittingOrder = codeEmittingOrder; @@ -98,6 +101,11 @@ this.lirInstructions = new BlockMap<>(cfg); stubs = new ArrayList<>(); + this.speculationLog = speculationLog; + } + + public SpeculationLog getDeoptimizationReasons() { + return speculationLog; } /**
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRFrameState.java Tue Mar 12 11:38:24 2013 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRFrameState.java Tue Mar 12 11:38:52 2013 +0100 @@ -42,11 +42,13 @@ private final VirtualObject[] virtualObjects; public final LabelRef exceptionEdge; private DebugInfo debugInfo; + private final short deoptimizationReason; - public LIRFrameState(BytecodeFrame topFrame, VirtualObject[] virtualObjects, LabelRef exceptionEdge) { + public LIRFrameState(BytecodeFrame topFrame, VirtualObject[] virtualObjects, LabelRef exceptionEdge, short deoptimizationReason) { this.topFrame = topFrame; this.virtualObjects = virtualObjects; this.exceptionEdge = exceptionEdge; + this.deoptimizationReason = deoptimizationReason; } public boolean hasDebugInfo() { @@ -111,7 +113,7 @@ } public void finish(BitSet registerRefMap, BitSet frameRefMap) { - debugInfo = new DebugInfo(topFrame, registerRefMap, frameRefMap); + debugInfo = new DebugInfo(topFrame, registerRefMap, frameRefMap, deoptimizationReason); } @Override
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstruction.java Tue Mar 12 11:38:24 2013 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstruction.java Tue Mar 12 11:38:52 2013 +0100 @@ -166,9 +166,9 @@ STACK, /** - * The value can be a {@link Address}. + * The value can be a {@link CompositeValue}. */ - ADDR, + COMPOSITE, /** * The value can be a {@link Constant}. @@ -205,10 +205,10 @@ static { ALLOWED_FLAGS = new EnumMap<>(OperandMode.class); - ALLOWED_FLAGS.put(USE, EnumSet.of(REG, STACK, ADDR, CONST, ILLEGAL, HINT, UNINITIALIZED)); - ALLOWED_FLAGS.put(ALIVE, EnumSet.of(REG, STACK, ADDR, CONST, ILLEGAL, HINT, UNINITIALIZED)); - ALLOWED_FLAGS.put(TEMP, EnumSet.of(REG, CONST, ILLEGAL, HINT)); - ALLOWED_FLAGS.put(DEF, EnumSet.of(REG, STACK, ILLEGAL, HINT)); + ALLOWED_FLAGS.put(USE, EnumSet.of(REG, STACK, COMPOSITE, CONST, ILLEGAL, HINT, UNUSED, UNINITIALIZED)); + ALLOWED_FLAGS.put(ALIVE, EnumSet.of(REG, STACK, COMPOSITE, CONST, ILLEGAL, HINT, UNUSED, UNINITIALIZED)); + ALLOWED_FLAGS.put(TEMP, EnumSet.of(REG, COMPOSITE, CONST, ILLEGAL, UNUSED, HINT)); + ALLOWED_FLAGS.put(DEF, EnumSet.of(REG, STACK, COMPOSITE, ILLEGAL, UNUSED, HINT)); } /**
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstructionClass.java Tue Mar 12 11:38:24 2013 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRInstructionClass.java Tue Mar 12 11:38:52 2013 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 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 @@ -22,12 +22,8 @@ */ package com.oracle.graal.lir; -import static com.oracle.graal.api.code.ValueUtil.*; - -import java.lang.annotation.*; import java.lang.reflect.*; import java.util.*; -import java.util.Map.Entry; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; @@ -37,7 +33,7 @@ import com.oracle.graal.lir.LIRInstruction.StateProcedure; import com.oracle.graal.lir.LIRInstruction.ValueProcedure; -public class LIRInstructionClass extends FieldIntrospection { +public class LIRInstructionClass extends LIRIntrospection { public static final LIRInstructionClass get(Class<? extends LIRInstruction> c) { LIRInstructionClass clazz = (LIRInstructionClass) allClasses.get(c); @@ -56,10 +52,8 @@ } } - private static final Class<?> INSTRUCTION_CLASS = LIRInstruction.class; - private static final Class<?> VALUE_CLASS = Value.class; - private static final Class<?> VALUE_ARRAY_CLASS = Value[].class; - private static final Class<?> STATE_CLASS = LIRFrameState.class; + private static final Class<LIRInstruction> INSTRUCTION_CLASS = LIRInstruction.class; + private static final Class<LIRFrameState> STATE_CLASS = LIRFrameState.class; private final int directUseCount; private final long[] useOffsets; @@ -80,11 +74,11 @@ private long opcodeOffset; @SuppressWarnings("unchecked") - public LIRInstructionClass(Class<?> clazz) { + public LIRInstructionClass(Class<? extends LIRInstruction> clazz) { super(clazz); assert INSTRUCTION_CLASS.isAssignableFrom(clazz); - FieldScanner scanner = new FieldScanner(new DefaultCalcOffset()); + InstructionFieldScanner scanner = new InstructionFieldScanner(new DefaultCalcOffset()); scanner.scan(clazz); OperandModeAnnotation mode = scanner.valueAnnotations.get(LIRInstruction.Use.class); @@ -119,7 +113,7 @@ @Override protected void rescanFieldOffsets(CalcOffset calc) { - FieldScanner scanner = new FieldScanner(calc); + InstructionFieldScanner scanner = new InstructionFieldScanner(calc); scanner.scan(clazz); OperandModeAnnotation mode = scanner.valueAnnotations.get(LIRInstruction.Use.class); @@ -143,44 +137,22 @@ opcodeOffset = scanner.opcodeOffset; } - private static class OperandModeAnnotation { - - public final ArrayList<Long> scalarOffsets = new ArrayList<>(); - public final ArrayList<Long> arrayOffsets = new ArrayList<>(); - public final Map<Long, EnumSet<OperandFlag>> flags = new HashMap<>(); - } - - protected static class FieldScanner extends BaseFieldScanner { - - public final Map<Class<? extends Annotation>, OperandModeAnnotation> valueAnnotations; - public final ArrayList<Long> stateOffsets = new ArrayList<>(); + private static class InstructionFieldScanner extends FieldScanner { private String opcodeConstant; private long opcodeOffset; - public FieldScanner(CalcOffset calc) { + public InstructionFieldScanner(CalcOffset calc) { super(calc); - valueAnnotations = new HashMap<>(); - valueAnnotations.put(LIRInstruction.Use.class, new OperandModeAnnotation()); // LIRInstruction.Use.class)); - valueAnnotations.put(LIRInstruction.Alive.class, new OperandModeAnnotation()); // LIRInstruction.Alive.class)); - valueAnnotations.put(LIRInstruction.Temp.class, new OperandModeAnnotation()); // LIRInstruction.Temp.class)); - valueAnnotations.put(LIRInstruction.Def.class, new OperandModeAnnotation()); // LIRInstruction.Def.class)); + valueAnnotations.put(LIRInstruction.Use.class, new OperandModeAnnotation()); + valueAnnotations.put(LIRInstruction.Alive.class, new OperandModeAnnotation()); + valueAnnotations.put(LIRInstruction.Temp.class, new OperandModeAnnotation()); + valueAnnotations.put(LIRInstruction.Def.class, new OperandModeAnnotation()); } - private OperandModeAnnotation getOperandModeAnnotation(Field field) { - OperandModeAnnotation result = null; - for (Entry<Class<? extends Annotation>, OperandModeAnnotation> entry : valueAnnotations.entrySet()) { - Annotation annotation = field.getAnnotation(entry.getKey()); - if (annotation != null) { - assert result == null : "Field has two operand mode annotations: " + field; - result = entry.getValue(); - } - } - return result; - } - - private static EnumSet<OperandFlag> getFlags(Field field) { + @Override + protected EnumSet<OperandFlag> getFlags(Field field) { EnumSet<OperandFlag> result = EnumSet.noneOf(OperandFlag.class); // Unfortunately, annotations cannot have class hierarchies or implement interfaces, so // we have to duplicate the code for every operand mode. @@ -219,26 +191,12 @@ @Override protected void scanField(Field field, Class<?> type, long offset) { - if (VALUE_CLASS.isAssignableFrom(type)) { - assert Modifier.isProtected(field.getModifiers()) && !Modifier.isFinal(field.getModifiers()) : "Value field must not be declared final or [package] private because it is modified by register allocator: " + - field; - OperandModeAnnotation annotation = getOperandModeAnnotation(field); - assert annotation != null : "Field must have operand mode annotation: " + field; - annotation.scalarOffsets.add(offset); - annotation.flags.put(offset, getFlags(field)); - } else if (VALUE_ARRAY_CLASS.isAssignableFrom(type)) { - OperandModeAnnotation annotation = getOperandModeAnnotation(field); - assert annotation != null : "Field must have operand mode annotation: " + field; - annotation.arrayOffsets.add(offset); - annotation.flags.put(offset, getFlags(field)); - } else if (STATE_CLASS.isAssignableFrom(type)) { + if (STATE_CLASS.isAssignableFrom(type)) { assert getOperandModeAnnotation(field) == null : "Field must not have operand mode annotation: " + field; assert field.getAnnotation(LIRInstruction.State.class) != null : "Field must have state annotation: " + field; stateOffsets.add(offset); } else { - assert getOperandModeAnnotation(field) == null : "Field must not have operand mode annotation: " + field; - assert field.getAnnotation(LIRInstruction.State.class) == null : "Field must not have state annotation: " + field; - dataOffsets.add(offset); + super.scanField(field, type, offset); } if (field.getAnnotation(LIRInstruction.Opcode.class) != null) { @@ -334,39 +292,6 @@ } } - private static void forEach(LIRInstruction obj, int directCount, long[] offsets, OperandMode mode, EnumSet<OperandFlag>[] flags, ValueProcedure proc) { - for (int i = 0; i < offsets.length; i++) { - assert LIRInstruction.ALLOWED_FLAGS.get(mode).containsAll(flags[i]); - - if (i < directCount) { - Value value = getValue(obj, offsets[i]); - if (isAddress(value)) { - doAddress(asAddress(value), mode, flags[i], proc); - } else { - setValue(obj, offsets[i], proc.doValue(value, mode, flags[i])); - } - } else { - Value[] values = getValueArray(obj, offsets[i]); - for (int j = 0; j < values.length; j++) { - Value value = values[j]; - if (isAddress(value)) { - doAddress(asAddress(value), mode, flags[i], proc); - } else { - values[j] = proc.doValue(value, mode, flags[i]); - } - } - } - } - } - - private static void doAddress(Address address, OperandMode mode, EnumSet<OperandFlag> flags, ValueProcedure proc) { - assert flags.contains(OperandFlag.ADDR); - Value[] components = address.components(); - for (int i = 0; i < components.length; i++) { - components[i] = proc.doValue(components[i], mode, LIRInstruction.ADDRESS_FLAGS); - } - } - public final Value forEachRegisterHint(LIRInstruction obj, OperandMode mode, ValueProcedure proc) { int hintDirectCount = 0; long[] hintOffsets = null; @@ -401,18 +326,6 @@ return null; } - private static Value getValue(LIRInstruction obj, long offset) { - return (Value) unsafe.getObject(obj, offset); - } - - private static void setValue(LIRInstruction obj, long offset, Value value) { - unsafe.putObject(obj, offset, value); - } - - private static Value[] getValueArray(LIRInstruction obj, long offset) { - return (Value[]) unsafe.getObject(obj, offset); - } - private static LIRFrameState getState(LIRInstruction obj, long offset) { return (LIRFrameState) unsafe.getObject(obj, offset); } @@ -447,65 +360,4 @@ return result.toString(); } - - private void appendValues(StringBuilder result, LIRInstruction obj, String start, String end, String startMultiple, String endMultiple, String[] prefix, long[]... moffsets) { - int total = 0; - for (long[] offsets : moffsets) { - total += offsets.length; - } - if (total == 0) { - return; - } - - result.append(start); - if (total > 1) { - result.append(startMultiple); - } - String sep = ""; - for (int i = 0; i < moffsets.length; i++) { - long[] offsets = moffsets[i]; - - for (int j = 0; j < offsets.length; j++) { - result.append(sep).append(prefix[i]); - long offset = offsets[j]; - if (total > 1) { - result.append(fieldNames.get(offset)).append(": "); - } - result.append(getFieldString(obj, offset)); - sep = ", "; - } - } - if (total > 1) { - result.append(endMultiple); - } - result.append(end); - } - - private String getFieldString(Object obj, long offset) { - Class<?> type = fieldTypes.get(offset); - if (type == int.class) { - return String.valueOf(unsafe.getInt(obj, offset)); - } else if (type == long.class) { - return String.valueOf(unsafe.getLong(obj, offset)); - } else if (type == boolean.class) { - return String.valueOf(unsafe.getBoolean(obj, offset)); - } else if (type == float.class) { - return String.valueOf(unsafe.getFloat(obj, offset)); - } else if (type == double.class) { - return String.valueOf(unsafe.getDouble(obj, offset)); - } else if (!type.isPrimitive()) { - Object value = unsafe.getObject(obj, offset); - if (!type.isArray()) { - return String.valueOf(value); - } else if (type == int[].class) { - return Arrays.toString((int[]) value); - } else if (type == double[].class) { - return Arrays.toString((double[]) value); - } else if (!type.getComponentType().isPrimitive()) { - return Arrays.toString((Object[]) value); - } - } - assert false : "unhandled field type: " + type; - return ""; - } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRIntrospection.java Tue Mar 12 11:38:52 2013 +0100 @@ -0,0 +1,220 @@ +/* + * 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 com.oracle.graal.lir; + +import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; + +import java.lang.annotation.*; +import java.lang.reflect.*; +import java.util.*; +import java.util.Map.Entry; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.lir.LIRInstruction.OperandFlag; +import com.oracle.graal.lir.LIRInstruction.OperandMode; +import com.oracle.graal.lir.LIRInstruction.ValueProcedure; + +abstract class LIRIntrospection extends FieldIntrospection { + + private static final Class<Value> VALUE_CLASS = Value.class; + private static final Class<Constant> CONSTANT_CLASS = Constant.class; + private static final Class<RegisterValue> REGISTER_VALUE_CLASS = RegisterValue.class; + private static final Class<StackSlot> STACK_SLOT_CLASS = StackSlot.class; + private static final Class<Value[]> VALUE_ARRAY_CLASS = Value[].class; + + public LIRIntrospection(Class<?> clazz) { + super(clazz); + } + + protected static class OperandModeAnnotation { + + public final ArrayList<Long> scalarOffsets = new ArrayList<>(); + public final ArrayList<Long> arrayOffsets = new ArrayList<>(); + public final Map<Long, EnumSet<OperandFlag>> flags = new HashMap<>(); + } + + protected abstract static class FieldScanner extends BaseFieldScanner { + + public final Map<Class<? extends Annotation>, OperandModeAnnotation> valueAnnotations; + public final ArrayList<Long> stateOffsets = new ArrayList<>(); + + public FieldScanner(CalcOffset calc) { + super(calc); + + valueAnnotations = new HashMap<>(); + } + + protected OperandModeAnnotation getOperandModeAnnotation(Field field) { + OperandModeAnnotation result = null; + for (Entry<Class<? extends Annotation>, OperandModeAnnotation> entry : valueAnnotations.entrySet()) { + Annotation annotation = field.getAnnotation(entry.getKey()); + if (annotation != null) { + assert result == null : "Field has two operand mode annotations: " + field; + result = entry.getValue(); + } + } + return result; + } + + protected abstract EnumSet<OperandFlag> getFlags(Field field); + + @Override + protected void scanField(Field field, Class<?> type, long offset) { + if (VALUE_CLASS.isAssignableFrom(type) && type != CONSTANT_CLASS) { + assert !Modifier.isFinal(field.getModifiers()) : "Value field must not be declared final because it is modified by register allocator: " + field; + OperandModeAnnotation annotation = getOperandModeAnnotation(field); + assert annotation != null : "Field must have operand mode annotation: " + field; + annotation.scalarOffsets.add(offset); + EnumSet<OperandFlag> flags = getFlags(field); + assert verifyFlags(field, type, flags); + annotation.flags.put(offset, getFlags(field)); + } else if (VALUE_ARRAY_CLASS.isAssignableFrom(type)) { + OperandModeAnnotation annotation = getOperandModeAnnotation(field); + assert annotation != null : "Field must have operand mode annotation: " + field; + annotation.arrayOffsets.add(offset); + EnumSet<OperandFlag> flags = getFlags(field); + assert verifyFlags(field, type.getComponentType(), flags); + annotation.flags.put(offset, getFlags(field)); + } else { + assert getOperandModeAnnotation(field) == null : "Field must not have operand mode annotation: " + field; + assert field.getAnnotation(LIRInstruction.State.class) == null : "Field must not have state annotation: " + field; + dataOffsets.add(offset); + } + } + + private static boolean verifyFlags(Field field, Class<?> type, EnumSet<OperandFlag> flags) { + if (flags.contains(REG)) { + assert type.isAssignableFrom(REGISTER_VALUE_CLASS) : "Cannot assign RegisterValue to field with REG flag:" + field; + } + if (flags.contains(STACK)) { + assert type.isAssignableFrom(STACK_SLOT_CLASS) : "Cannot assign StackSlot to field with STACK flag:" + field; + } + if (flags.contains(CONST)) { + assert type.isAssignableFrom(CONSTANT_CLASS) : "Cannot assign Constant to field with CONST flag:" + field; + } + return true; + } + } + + protected static void forEach(Object obj, int directCount, long[] offsets, OperandMode mode, EnumSet<OperandFlag>[] flags, ValueProcedure proc) { + for (int i = 0; i < offsets.length; i++) { + assert LIRInstruction.ALLOWED_FLAGS.get(mode).containsAll(flags[i]); + + if (i < directCount) { + Value value = getValue(obj, offsets[i]); + if (value instanceof CompositeValue) { + CompositeValue composite = (CompositeValue) value; + composite.forEachComponent(mode, proc); + } else { + setValue(obj, offsets[i], proc.doValue(value, mode, flags[i])); + } + } else { + Value[] values = getValueArray(obj, offsets[i]); + for (int j = 0; j < values.length; j++) { + Value value = values[j]; + if (value instanceof CompositeValue) { + CompositeValue composite = (CompositeValue) value; + composite.forEachComponent(mode, proc); + } else { + values[j] = proc.doValue(value, mode, flags[i]); + } + } + } + } + } + + protected static Value getValue(Object obj, long offset) { + return (Value) unsafe.getObject(obj, offset); + } + + protected static void setValue(Object obj, long offset, Value value) { + unsafe.putObject(obj, offset, value); + } + + protected static Value[] getValueArray(Object obj, long offset) { + return (Value[]) unsafe.getObject(obj, offset); + } + + protected void appendValues(StringBuilder result, Object obj, String start, String end, String startMultiple, String endMultiple, String[] prefix, long[]... moffsets) { + int total = 0; + for (long[] offsets : moffsets) { + total += offsets.length; + } + if (total == 0) { + return; + } + + result.append(start); + if (total > 1) { + result.append(startMultiple); + } + String sep = ""; + for (int i = 0; i < moffsets.length; i++) { + long[] offsets = moffsets[i]; + + for (int j = 0; j < offsets.length; j++) { + result.append(sep).append(prefix[i]); + long offset = offsets[j]; + if (total > 1) { + result.append(fieldNames.get(offset)).append(": "); + } + result.append(getFieldString(obj, offset)); + sep = ", "; + } + } + if (total > 1) { + result.append(endMultiple); + } + result.append(end); + } + + protected String getFieldString(Object obj, long offset) { + Class<?> type = fieldTypes.get(offset); + if (type == int.class) { + return String.valueOf(unsafe.getInt(obj, offset)); + } else if (type == long.class) { + return String.valueOf(unsafe.getLong(obj, offset)); + } else if (type == boolean.class) { + return String.valueOf(unsafe.getBoolean(obj, offset)); + } else if (type == float.class) { + return String.valueOf(unsafe.getFloat(obj, offset)); + } else if (type == double.class) { + return String.valueOf(unsafe.getDouble(obj, offset)); + } else if (!type.isPrimitive()) { + Object value = unsafe.getObject(obj, offset); + if (!type.isArray()) { + return String.valueOf(value); + } else if (type == int[].class) { + return Arrays.toString((int[]) value); + } else if (type == double[].class) { + return Arrays.toString((double[]) value); + } else if (!type.getComponentType().isPrimitive()) { + return Arrays.toString((Object[]) value); + } + } + assert false : "unhandled field type: " + type; + return ""; + } +}
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/TargetMethodAssembler.java Tue Mar 12 11:38:24 2013 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/TargetMethodAssembler.java Tue Mar 12 11:38:52 2013 +0100 @@ -32,7 +32,6 @@ import com.oracle.graal.debug.*; import com.oracle.graal.graph.*; import com.oracle.graal.lir.*; -import com.oracle.graal.lir.LIR.Code; public class TargetMethodAssembler { @@ -54,11 +53,6 @@ public final FrameMap frameMap; /** - * Out-of-line stubs to be emitted. - */ - public final List<Code> stubs; - - /** * The object that emits code for managing a method's frame. If null, no frame is used by the * method. */ @@ -66,11 +60,10 @@ private List<ExceptionInfo> exceptionInfoList; - public TargetMethodAssembler(TargetDescription target, CodeCacheProvider runtime, FrameMap frameMap, AbstractAssembler asm, FrameContext frameContext, List<Code> stubs) { + public TargetMethodAssembler(TargetDescription target, CodeCacheProvider runtime, FrameMap frameMap, AbstractAssembler asm, FrameContext frameContext) { this.target = target; this.runtime = runtime; this.frameMap = frameMap; - this.stubs = stubs; this.asm = asm; this.compilationResult = new CompilationResult(); this.frameContext = frameContext; @@ -150,7 +143,7 @@ compilationResult.recordSafepoint(pos, debugInfo); } - public Address recordDataReferenceInCode(Constant data, int alignment, boolean inlined) { + public AbstractAddress recordDataReferenceInCode(Constant data, int alignment, boolean inlined) { assert data != null; int pos = asm.codeBuffer.position(); Debug.log("Data reference in code: pos = %d, data = %s", pos, data.toString()); @@ -176,11 +169,11 @@ /** * Returns the address of a float constant that is embedded as a data references into the code. */ - public Address asFloatConstRef(Value value) { + public AbstractAddress asFloatConstRef(Value value) { return asFloatConstRef(value, 4); } - public Address asFloatConstRef(Value value, int alignment) { + public AbstractAddress asFloatConstRef(Value value, int alignment) { assert value.getKind() == Kind.Float && isConstant(value); return recordDataReferenceInCode((Constant) value, alignment, false); } @@ -188,11 +181,11 @@ /** * Returns the address of a double constant that is embedded as a data references into the code. */ - public Address asDoubleConstRef(Value value) { + public AbstractAddress asDoubleConstRef(Value value) { return asDoubleConstRef(value, 8); } - public Address asDoubleConstRef(Value value, int alignment) { + public AbstractAddress asDoubleConstRef(Value value, int alignment) { assert value.getKind() == Kind.Double && isConstant(value); return recordDataReferenceInCode((Constant) value, alignment, false); } @@ -200,41 +193,39 @@ /** * Returns the address of a long constant that is embedded as a data references into the code. */ - public Address asLongConstRef(Value value) { + public AbstractAddress asLongConstRef(Value value) { assert value.getKind() == Kind.Long && isConstant(value); return recordDataReferenceInCode((Constant) value, 8, false); } - public Address asIntAddr(Value value) { + public AbstractAddress asIntAddr(Value value) { assert value.getKind() == Kind.Int; return asAddress(value); } - public Address asLongAddr(Value value) { + public AbstractAddress asLongAddr(Value value) { assert value.getKind() == Kind.Long; return asAddress(value); } - public Address asObjectAddr(Value value) { + public AbstractAddress asObjectAddr(Value value) { assert value.getKind() == Kind.Object; return asAddress(value); } - public Address asFloatAddr(Value value) { + public AbstractAddress asFloatAddr(Value value) { assert value.getKind() == Kind.Float; return asAddress(value); } - public Address asDoubleAddr(Value value) { + public AbstractAddress asDoubleAddr(Value value) { assert value.getKind() == Kind.Double; return asAddress(value); } - public Address asAddress(Value value) { - if (isStackSlot(value)) { - StackSlot slot = (StackSlot) value; - return asm.makeAddress(slot.getKind(), frameMap.registerConfig.getFrameRegister().asValue(), frameMap.offsetForStackSlot(slot)); - } - return (Address) value; + public AbstractAddress asAddress(Value value) { + assert isStackSlot(value); + StackSlot slot = asStackSlot(value); + return asm.makeAddress(frameMap.registerConfig.getFrameRegister(), frameMap.offsetForStackSlot(slot)); } }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizeNode.java Tue Mar 12 11:38:24 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/DeoptimizeNode.java Tue Mar 12 11:38:52 2013 +0100 @@ -31,7 +31,6 @@ @NodeInfo(shortName = "Deopt", nameTemplate = "Deopt {p#reason/s}") public class DeoptimizeNode extends FixedNode implements Node.IterableNodeType, LIRLowerable { - private String message; private final DeoptimizationAction action; private final DeoptimizationReason reason; @@ -41,14 +40,6 @@ this.reason = reason; } - public void setMessage(String message) { - this.message = message; - } - - public String message() { - return message; - } - public DeoptimizationAction action() { return action; } @@ -59,7 +50,7 @@ @Override public void generate(LIRGeneratorTool gen) { - gen.emitDeoptimize(action, reason, message); + gen.emitDeoptimize(action, reason); } @NodeIntrinsic
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java Tue Mar 12 11:38:24 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java Tue Mar 12 11:38:52 2013 +0100 @@ -152,10 +152,8 @@ ((StructuredGraph) graph()).removeSplit(this, falseSuccessor()); } } else if (trueSuccessor().guards().isEmpty() && falseSuccessor().guards().isEmpty()) { - if (removeOrMaterializeIf(tool)) { - return; - } else if (removeIntermediateMaterialization(tool)) { - return; + if (!removeOrMaterializeIf(tool)) { + removeIntermediateMaterialization(tool); } } }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/SafepointNode.java Tue Mar 12 11:38:24 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/SafepointNode.java Tue Mar 12 11:38:52 2013 +0100 @@ -29,10 +29,14 @@ /** * Marks a position in the graph where a safepoint should be emitted. */ -public final class SafepointNode extends FixedWithNextNode implements LIRLowerable, Node.IterableNodeType { +public class SafepointNode extends FixedWithNextNode implements LIRLowerable, Node.IterableNodeType { public SafepointNode() { - super(StampFactory.forVoid()); + this(StampFactory.forVoid()); + } + + public SafepointNode(Stamp stamp) { + super(stamp); } @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/UnwindNode.java Tue Mar 12 11:38:24 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/UnwindNode.java Tue Mar 12 11:38:52 2013 +0100 @@ -22,8 +22,6 @@ */ package com.oracle.graal.nodes; -import com.oracle.graal.api.code.*; -import com.oracle.graal.api.code.RuntimeCallTarget.Descriptor; import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.spi.*; @@ -35,8 +33,6 @@ */ public final class UnwindNode extends FixedNode implements LIRLowerable, Node.IterableNodeType { - public static final Descriptor UNWIND_EXCEPTION = new Descriptor("unwindException", true, void.class, Object.class); - @Input private ValueNode exception; public ValueNode exception() { @@ -51,7 +47,6 @@ @Override public void generate(LIRGeneratorTool gen) { - RuntimeCallTarget call = gen.getRuntime().lookupRuntimeCall(UNWIND_EXCEPTION); - gen.emitCall(call, call.getCallingConvention(), false, gen.operand(exception())); + gen.emitUnwind(gen.operand(exception())); } }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConvertNode.java Tue Mar 12 11:38:24 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConvertNode.java Tue Mar 12 11:38:52 2013 +0100 @@ -32,7 +32,7 @@ /** * The {@code ConvertNode} class represents a conversion between primitive types. */ -public final class ConvertNode extends FloatingNode implements Canonicalizable, LIRLowerable { +public final class ConvertNode extends FloatingNode implements Canonicalizable, LIRLowerable, Lowerable { public enum Op { I2L(Int, Long), @@ -162,6 +162,11 @@ } @Override + public void lower(LoweringTool tool) { + tool.getRuntime().lower(this, tool); + } + + @Override public void generate(LIRGeneratorTool gen) { gen.setResult(this, gen.emitConvert(opcode, gen.operand(value()))); }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/Block.java Tue Mar 12 11:38:24 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/Block.java Tue Mar 12 11:38:52 2013 +0100 @@ -47,6 +47,7 @@ protected Block() { id = ControlFlowGraph.BLOCK_ID_INITIAL; + this.linearScanNumber = -1; } public int getId() {
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeCastNode.java Tue Mar 12 11:38:24 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeCastNode.java Tue Mar 12 11:38:52 2013 +0100 @@ -53,6 +53,9 @@ if (kind() != Kind.Object || object().kind() != Kind.Object) { return false; } + if (stamp() == StampFactory.forNodeIntrinsic()) { + return false; + } if (object().objectStamp().alwaysNull() && objectStamp().nonNull()) { // a null value flowing into a nonNull UnsafeCastNode should be guarded by a type/isNull // guard, but the
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRGeneratorTool.java Tue Mar 12 11:38:24 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRGeneratorTool.java Tue Mar 12 11:38:52 2013 +0100 @@ -49,7 +49,7 @@ public abstract Value operand(ValueNode object); - public abstract Value newVariable(Kind kind); + public abstract AllocatableValue newVariable(Kind kind); public abstract Value setResult(ValueNode x, Value operand); @@ -97,9 +97,9 @@ public abstract void emitMembar(int barriers); - public abstract void emitDeoptimizeOnOverflow(DeoptimizationAction action, DeoptimizationReason reason, Object deoptInfo); + public abstract void emitDeoptimizeOnOverflow(DeoptimizationAction action, DeoptimizationReason reason); - public abstract void emitDeoptimize(DeoptimizationAction action, DeoptimizationReason reason, Object deoptInfo); + public abstract void emitDeoptimize(DeoptimizationAction action, DeoptimizationReason reason); public abstract Value emitCall(RuntimeCallTarget callTarget, CallingConvention cc, boolean canTrap, Value... args); @@ -132,4 +132,6 @@ public abstract void visitSafepointNode(SafepointNode i); public abstract void visitBreakpointNode(BreakpointNode i); + + public abstract void emitUnwind(Value operand); }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LoweringTool.java Tue Mar 12 11:38:24 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LoweringTool.java Tue Mar 12 11:38:52 2013 +0100 @@ -48,4 +48,9 @@ * Gets the closest fixed node preceding the node currently being lowered. */ FixedWithNextNode lastFixedNode(); + + /** + * Sets the closest fixed node preceding the next node to be lowered. + */ + void setLastFixedNode(FixedWithNextNode n); }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/GuardLoweringPhase.java Tue Mar 12 11:38:52 2013 +0100 @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2013, 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.graal.phases.common; + +import java.util.*; + +import com.oracle.graal.graph.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.cfg.*; +import com.oracle.graal.phases.*; +import com.oracle.graal.phases.schedule.*; + +public class GuardLoweringPhase extends Phase { + + @Override + protected void run(StructuredGraph graph) { + SchedulePhase schedule = new SchedulePhase(); + schedule.apply(graph); + + for (Block block : schedule.getCFG().getBlocks()) { + processBlock(block, schedule, graph); + } + } + + private static void processBlock(Block block, SchedulePhase schedule, StructuredGraph graph) { + List<ScheduledNode> nodes = schedule.nodesFor(block); + FixedWithNextNode lastFixed = block.getBeginNode(); + BeginNode lastFastPath = null; + for (Node node : nodes) { + if (lastFastPath != null && node instanceof FixedNode) { + lastFastPath.setNext((FixedNode) node); + lastFastPath = null; + } + if (node instanceof FixedWithNextNode) { + lastFixed = (FixedWithNextNode) node; + } else if (node instanceof GuardNode) { + GuardNode guard = (GuardNode) node; + BeginNode fastPath = graph.add(new BeginNode()); + BeginNode trueSuccessor; + BeginNode falseSuccessor; + DeoptimizeNode deopt = graph.add(new DeoptimizeNode(guard.action(), guard.reason())); + if (guard.negated()) { + trueSuccessor = BeginNode.begin(deopt); + falseSuccessor = fastPath; + } else { + trueSuccessor = fastPath; + falseSuccessor = BeginNode.begin(deopt); + } + IfNode ifNode = graph.add(new IfNode(guard.condition(), trueSuccessor, falseSuccessor, trueSuccessor == fastPath ? 1 : 0)); + guard.replaceAndDelete(fastPath); + lastFixed.setNext(ifNode); + lastFixed = fastPath; + lastFastPath = fastPath; + } + } + } +}
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoopSafepointInsertionPhase.java Tue Mar 12 11:38:24 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,55 +0,0 @@ -/* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. - * 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.graal.phases.common; - -import com.oracle.graal.graph.iterators.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.util.*; -import com.oracle.graal.phases.*; - -/** - * Adds safepoints to loops. - */ -public class LoopSafepointInsertionPhase extends Phase { - - @Override - protected void run(StructuredGraph graph) { - nextLoop: for (LoopEndNode loopEnd : graph.getNodes(LoopEndNode.class)) { - if (!loopEnd.canSafepoint()) { - continue; - } - if (GraalOptions.OptSafepointElimination) { - // We 'eliminate' safepoints by simply never placing them into loops that have at - // least one call - NodeIterable<FixedNode> it = NodeIterators.dominators(loopEnd).until(loopEnd.loopBegin()); - for (FixedNode n : it) { - if (n instanceof Invoke) { - continue nextLoop; - } - } - } - SafepointNode safepoint = graph.add(new SafepointNode()); - graph.addBeforeFixed(loopEnd, safepoint); - } - } -}
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoweringPhase.java Tue Mar 12 11:38:24 2013 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoweringPhase.java Tue Mar 12 11:38:52 2013 +0100 @@ -104,6 +104,11 @@ public FixedWithNextNode lastFixedNode() { return lastFixedNode; } + + public void setLastFixedNode(FixedWithNextNode n) { + assert n == null || n.isAlive() : n; + lastFixedNode = n; + } } private final TargetDescription target; @@ -187,15 +192,15 @@ List<ScheduledNode> nodes = schedule.nodesFor(b); for (Node node : nodes) { - FixedNode lastFixedNext = null; - if (node instanceof FixedWithNextNode) { + FixedNode nextFixedNode = null; + if (node instanceof FixedWithNextNode && node.isAlive()) { FixedWithNextNode fixed = (FixedWithNextNode) node; - lastFixedNext = fixed.next(); - loweringTool.lastFixedNode = fixed; + nextFixedNode = fixed.next(); + loweringTool.setLastFixedNode(fixed); } if (node.isAlive() && !processed.isMarked(node) && node instanceof Lowerable) { - if (loweringTool.lastFixedNode == null) { + if (loweringTool.lastFixedNode() == null) { // We cannot lower the node now because we don't have a fixed node to anchor the // replacements. // This can happen when previous lowerings in this lowering iteration deleted @@ -209,17 +214,17 @@ } } - if (loweringTool.lastFixedNode == node && !node.isAlive()) { - if (lastFixedNext == null) { - loweringTool.lastFixedNode = null; + if (loweringTool.lastFixedNode() == node && !node.isAlive()) { + if (nextFixedNode == null || !nextFixedNode.isAlive()) { + loweringTool.setLastFixedNode(null); } else { - Node prev = lastFixedNext.predecessor(); + Node prev = nextFixedNode.predecessor(); if (prev != node && prev instanceof FixedWithNextNode) { - loweringTool.lastFixedNode = (FixedWithNextNode) prev; - } else if (lastFixedNext instanceof FixedWithNextNode) { - loweringTool.lastFixedNode = (FixedWithNextNode) lastFixedNext; + loweringTool.setLastFixedNode((FixedWithNextNode) prev); + } else if (nextFixedNode instanceof FixedWithNextNode) { + loweringTool.setLastFixedNode((FixedWithNextNode) nextFixedNode); } else { - loweringTool.lastFixedNode = null; + loweringTool.setLastFixedNode(null); } } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/SafepointInsertionPhase.java Tue Mar 12 11:38:52 2013 +0100 @@ -0,0 +1,55 @@ +/* + * 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 + * 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.graal.phases.common; + +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.java.*; +import com.oracle.graal.phases.*; + +/** + * Adds safepoints to loops and return points. + */ +public class SafepointInsertionPhase extends Phase { + + @Override + protected void run(StructuredGraph graph) { + if (GraalOptions.GenLoopSafepoints) { + for (LoopEndNode loopEndNode : graph.getNodes(LoopEndNode.class)) { + if (!loopEndNode.canSafepoint()) { + continue; + } + SafepointNode safepointNode = graph.add(new SafepointNode()); + graph.addBeforeFixed(loopEndNode, safepointNode); + } + } + + if (GraalOptions.GenSafepoints) { + if (!GraalOptions.OptEliminateSafepoints || graph.getNodes(MethodCallTargetNode.class).isNotEmpty()) { + for (ReturnNode returnNode : graph.getNodes(ReturnNode.class)) { + SafepointNode safepoint = graph.add(new SafepointNode()); + graph.addBeforeFixed(returnNode, safepoint); + } + } + } + } +}
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java Tue Mar 12 11:38:24 2013 +0100 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java Tue Mar 12 11:38:52 2013 +0100 @@ -109,7 +109,6 @@ public static boolean ZapStackOnMethodEntry = ____; public static boolean DeoptALot = ____; public static boolean VerifyPhases = true; - public static boolean CreateDeoptInfo = ____; public static String PrintFilter = null; @@ -165,7 +164,7 @@ public static boolean GenAssertionCode = ____; public static boolean AlignCallsForPatching = true; public static boolean ResolveClassBeforeStaticInvoke = ____; - public static boolean CanOmitFrame = true; + public static boolean CanOmitFrame = false; public static int SafepointPollOffset = 256; public static boolean MemoryAwareScheduling = true; @@ -187,10 +186,10 @@ public static boolean OptCanonicalizer = true; public static boolean OptScheduleOutOfLoops = true; public static boolean OptEliminateGuards = true; + public static boolean OptEliminateSafepoints = true; public static boolean OptImplicitNullChecks = true; public static boolean OptLivenessAnalysis = true; public static boolean OptLoopTransform = true; - public static boolean OptSafepointElimination = true; public static boolean OptFloatingReads = true; public static boolean OptTailDuplication = true; public static boolean OptEliminatePartiallyRedundantGuards = true;
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java Tue Mar 12 11:38:24 2013 +0100 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java Tue Mar 12 11:38:52 2013 +0100 @@ -45,7 +45,7 @@ /** * This closure iterates over all nodes of a scheduled graph (it expects a - * {@link SchedulingStrategy#EARLIEST} schedule) and keeps a list of "actuve" reads. Whenever it + * {@link SchedulingStrategy#EARLIEST} schedule) and keeps a list of "active" reads. Whenever it * encounters a read, it adds it to the active reads. Whenever it encounters a memory * checkpoint, it adds all reads that need to be committed before this checkpoint to the * "phantom" usages and inputs, so that the read is scheduled before the checkpoint afterwards. @@ -135,10 +135,6 @@ private final Map<FloatingNode, List<FixedNode>> phantomUsages = new IdentityHashMap<>(); private final Map<FixedNode, List<FloatingNode>> phantomInputs = new IdentityHashMap<>(); - public SchedulePhase() { - super("Schedule"); - } - @Override protected void run(StructuredGraph graph) { SchedulingStrategy strategy = GraalOptions.OptScheduleOutOfLoops ? SchedulingStrategy.LATEST_OUT_OF_LOOPS : SchedulingStrategy.LATEST;
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinterObserver.java Tue Mar 12 11:38:24 2013 +0100 +++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinterObserver.java Tue Mar 12 11:38:52 2013 +0100 @@ -54,6 +54,7 @@ dumpSandboxed(object, message); } catch (Throwable ex) { TTY.println("CFGPrinter: Exception during output of " + message + ": " + ex); + ex.printStackTrace(); } } @@ -115,18 +116,23 @@ return; } - cfgPrinter.target = Debug.contextLookup(TargetDescription.class); if (object instanceof LIR) { cfgPrinter.lir = (LIR) object; } else { cfgPrinter.lir = Debug.contextLookup(LIR.class); } cfgPrinter.lirGenerator = Debug.contextLookup(LIRGenerator.class); + if (cfgPrinter.lirGenerator != null) { + cfgPrinter.target = cfgPrinter.lirGenerator.target(); + } if (cfgPrinter.lir != null) { cfgPrinter.cfg = cfgPrinter.lir.cfg; } CodeCacheProvider runtime = Debug.contextLookup(CodeCacheProvider.class); + if (runtime != null) { + cfgPrinter.target = runtime.getTarget(); + } if (object instanceof BciBlockMapping) { BciBlockMapping blockMap = (BciBlockMapping) object;
--- a/graal/com.oracle.graal.ptx/src/com/oracle/graal/ptx/PTXAddress.java Tue Mar 12 11:38:24 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,123 +0,0 @@ -/* - * 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.graal.ptx; - -import static com.oracle.graal.api.code.ValueUtil.*; - -import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; - -/** - * Represents an address in target machine memory, specified via some combination of a base register - * and a displacement. - */ -public final class PTXAddress extends Address { - - private static final long serialVersionUID = 8343625682010474837L; - - private final Value[] base; - private final long displacement; - - /** - * Creates an {@link PTXAddress} with given base register and no displacement. - * - * @param kind the kind of the value being addressed - * @param base the base register - */ - public PTXAddress(Kind kind, Value base) { - this(kind, base, 0); - } - - /** - * Creates an {@link PTXAddress} with given base register and a displacement. This is the most - * general constructor. - * - * @param kind the kind of the value being addressed - * @param base the base register - * @param displacement the displacement - */ - public PTXAddress(Kind kind, Value base, long displacement) { - super(kind); - this.base = new Value[1]; - this.setBase(base); - this.displacement = displacement; - - assert !isConstant(base) && !isStackSlot(base); - } - - @Override - public Value[] components() { - return base; - } - - @Override - public String toString() { - StringBuilder s = new StringBuilder(); - s.append(getKind().getJavaName()).append("["); - String sep = ""; - if (isLegal(getBase())) { - s.append(getBase()); - sep = " + "; - } - if (getDisplacement() < 0) { - s.append(" - ").append(-getDisplacement()); - } else if (getDisplacement() > 0) { - s.append(sep).append(getDisplacement()); - } - s.append("]"); - return s.toString(); - } - - @Override - public boolean equals(Object obj) { - if (obj instanceof PTXAddress) { - PTXAddress addr = (PTXAddress) obj; - return getKind() == addr.getKind() && getDisplacement() == addr.getDisplacement() && getBase().equals(addr.getBase()); - } - return false; - } - - @Override - public int hashCode() { - return getBase().hashCode() ^ ((int) getDisplacement() << 4) ^ (getKind().ordinal() << 12); - } - - /** - * @return Base register that defines the start of the address computation. If not present, is - * denoted by {@link Value#ILLEGAL}. - */ - public Value getBase() { - return base[0]; - } - - public void setBase(Value base) { - this.base[0] = base; - } - - /** - * @return Optional additive displacement. - */ - public long getDisplacement() { - return displacement; - } -}
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/InstanceOfSnippetsTemplates.java Tue Mar 12 11:38:24 2013 +0100 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/InstanceOfSnippetsTemplates.java Tue Mar 12 11:38:52 2013 +0100 @@ -95,7 +95,7 @@ } else { KeyAndArguments keyAndArguments = getKeyAndArguments(replacer, tool); SnippetTemplate template = cache.get(keyAndArguments.key, assumptions); - template.instantiate(runtime, instanceOf, replacer, tool.lastFixedNode(), keyAndArguments.arguments); + template.instantiate(runtime, instanceOf, replacer, tool, keyAndArguments.arguments); } }
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetInstaller.java Tue Mar 12 11:38:24 2013 +0100 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetInstaller.java Tue Mar 12 11:38:52 2013 +0100 @@ -53,10 +53,10 @@ */ public class SnippetInstaller { - private final MetaAccessProvider runtime; - private final TargetDescription target; - private final Assumptions assumptions; - private final BoxingMethodPool pool; + protected final MetaAccessProvider runtime; + protected final TargetDescription target; + protected final Assumptions assumptions; + protected final BoxingMethodPool pool; private final Thread owner; /** @@ -191,6 +191,19 @@ } } + /** + * Does final processing of a snippet graph. + */ + protected void finalizeGraph(ResolvedJavaMethod method, StructuredGraph graph) { + new SnippetIntrinsificationPhase(runtime, pool).apply(graph); + assert SnippetTemplate.hasConstantParameter(method) || SnippetIntrinsificationVerificationPhase.verify(graph); + + new SnippetFrameStateCleanupPhase().apply(graph); + new DeadCodeEliminationPhase().apply(graph); + + new InsertStateAfterPlaceholderPhase().apply(graph); + } + public StructuredGraph makeGraph(final ResolvedJavaMethod method, final SnippetInliningPolicy policy) { return Debug.scope("BuildSnippetGraph", new Object[]{method}, new Callable<StructuredGraph>() { @@ -198,12 +211,7 @@ public StructuredGraph call() throws Exception { StructuredGraph graph = parseGraph(method, policy); - new SnippetIntrinsificationPhase(runtime, pool, SnippetTemplate.hasConstantParameter(method)).apply(graph); - - new SnippetFrameStateCleanupPhase().apply(graph); - new DeadCodeEliminationPhase().apply(graph); - - new InsertStateAfterPlaceholderPhase().apply(graph); + finalizeGraph(method, graph); Debug.dump(graph, "%s: Final", method.getName()); @@ -221,8 +229,10 @@ return graph; } - private StructuredGraph buildGraph(final ResolvedJavaMethod method, final SnippetInliningPolicy policy) { - assert !Modifier.isAbstract(method.getModifiers()) && !Modifier.isNative(method.getModifiers()) : method; + /** + * Builds the initial graph for a snippet. + */ + protected StructuredGraph buildInitialGraph(final ResolvedJavaMethod method) { final StructuredGraph graph = new StructuredGraph(method); GraphBuilderConfiguration config = GraphBuilderConfiguration.getSnippetDefault(); GraphBuilderPhase graphBuilder = new GraphBuilderPhase(runtime, config, OptimisticOptimizations.NONE); @@ -231,8 +241,41 @@ Debug.dump(graph, "%s: %s", method.getName(), GraphBuilderPhase.class.getSimpleName()); new WordTypeVerificationPhase(runtime, target.wordKind).apply(graph); + new SnippetIntrinsificationPhase(runtime, pool).apply(graph); - new SnippetIntrinsificationPhase(runtime, pool, true).apply(graph); + return graph; + } + + /** + * Called after a graph is inlined. + * + * @param caller the graph into which {@code callee} was inlined + * @param callee the graph that was inlined into {@code caller} + */ + protected void afterInline(StructuredGraph caller, StructuredGraph callee) { + if (GraalOptions.OptCanonicalizer) { + new WordTypeRewriterPhase(runtime, target.wordKind).apply(caller); + new CanonicalizerPhase(runtime, assumptions).apply(caller); + } + } + + /** + * Called after all inlining for a given graph is complete. + */ + protected void afterInlining(StructuredGraph graph) { + new SnippetIntrinsificationPhase(runtime, pool).apply(graph); + + new WordTypeRewriterPhase(runtime, target.wordKind).apply(graph); + + new DeadCodeEliminationPhase().apply(graph); + if (GraalOptions.OptCanonicalizer) { + new CanonicalizerPhase(runtime, assumptions).apply(graph); + } + } + + private StructuredGraph buildGraph(final ResolvedJavaMethod method, final SnippetInliningPolicy policy) { + assert !Modifier.isAbstract(method.getModifiers()) && !Modifier.isNative(method.getModifiers()) : method; + final StructuredGraph graph = buildInitialGraph(method); for (Invoke invoke : graph.getInvokes()) { MethodCallTargetNode callTarget = invoke.methodCallTarget(); @@ -243,31 +286,19 @@ InliningUtil.inline(invoke, originalGraph, true); Debug.dump(graph, "after inlining %s", callee); - if (GraalOptions.OptCanonicalizer) { - new CanonicalizerPhase(runtime, assumptions).apply(graph); - } + afterInline(graph, originalGraph); substituteCallsOriginal = true; } else { if ((callTarget.invokeKind() == InvokeKind.Static || callTarget.invokeKind() == InvokeKind.Special) && policy.shouldInline(callee, method)) { StructuredGraph targetGraph = parseGraph(callee, policy); InliningUtil.inline(invoke, targetGraph, true); Debug.dump(graph, "after inlining %s", callee); - if (GraalOptions.OptCanonicalizer) { - new WordTypeRewriterPhase(runtime, target.wordKind).apply(graph); - new CanonicalizerPhase(runtime, assumptions).apply(graph); - } + afterInline(graph, targetGraph); } } } - new SnippetIntrinsificationPhase(runtime, pool, true).apply(graph); - - new WordTypeRewriterPhase(runtime, target.wordKind).apply(graph); - - new DeadCodeEliminationPhase().apply(graph); - if (GraalOptions.OptCanonicalizer) { - new CanonicalizerPhase(runtime, assumptions).apply(graph); - } + afterInlining(graph); for (LoopEndNode end : graph.getNodes(LoopEndNode.class)) { end.disableSafepoint();
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetIntrinsificationPhase.java Tue Mar 12 11:38:24 2013 +0100 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetIntrinsificationPhase.java Tue Mar 12 11:38:52 2013 +0100 @@ -43,45 +43,21 @@ private final MetaAccessProvider runtime; private final BoxingMethodPool pool; - private final boolean intrinsificationOrFoldingCanBeDeferred; - /** - * @param intrinsificationOrFoldingCanBeDeferred if true, then {@link NonConstantParameterError} - * s are not fatal - */ - public SnippetIntrinsificationPhase(MetaAccessProvider runtime, BoxingMethodPool pool, boolean intrinsificationOrFoldingCanBeDeferred) { + public SnippetIntrinsificationPhase(MetaAccessProvider runtime, BoxingMethodPool pool) { this.runtime = runtime; this.pool = pool; - this.intrinsificationOrFoldingCanBeDeferred = intrinsificationOrFoldingCanBeDeferred; } @Override protected void run(StructuredGraph graph) { for (Invoke i : graph.getInvokes()) { - try { - if (i.callTarget() instanceof MethodCallTargetNode) { - tryIntrinsify(i); - } - } catch (NonConstantParameterError t) { - if (!intrinsificationOrFoldingCanBeDeferred) { - throw t; - } + if (i.callTarget() instanceof MethodCallTargetNode) { + tryIntrinsify(i); } } } - /** - * Exception raised when an argument to a {@linkplain Fold foldable} or {@link NodeIntrinsic} - * method is not a constant. - */ - @SuppressWarnings("serial") - public static class NonConstantParameterError extends Error { - - public NonConstantParameterError(String message) { - super(message); - } - } - public static Class<?>[] signatureToTypes(Signature signature, ResolvedJavaType accessingClass) { int count = signature.getParameterCount(false); Class<?>[] result = new Class<?>[count]; @@ -91,7 +67,7 @@ return result; } - private void tryIntrinsify(Invoke invoke) { + private boolean tryIntrinsify(Invoke invoke) { ResolvedJavaMethod target = invoke.methodCallTarget().targetMethod(); NodeIntrinsic intrinsic = target.getAnnotation(Node.NodeIntrinsic.class); ResolvedJavaType declaringClass = target.getDeclaringClass(); @@ -104,6 +80,9 @@ // Prepare the arguments for the reflective constructor call on the node class. Object[] nodeConstructorArguments = prepareArguments(invoke, parameterTypes, target, false); + if (nodeConstructorArguments == null) { + return false; + } // Create the new node instance. Class<?> c = getNodeClass(target, intrinsic); @@ -120,6 +99,9 @@ // Prepare the arguments for the reflective method call Object[] arguments = prepareArguments(invoke, parameterTypes, target, true); + if (arguments == null) { + return false; + } Object receiver = null; if (!invoke.methodCallTarget().isStatic()) { receiver = arguments[0]; @@ -142,6 +124,7 @@ invoke.intrinsify(null); } } + return true; } /** @@ -149,6 +132,8 @@ * to a reflective invocation of a Java constructor or method. * * @param folding specifies if the invocation is for handling a {@link Fold} annotation + * @return the arguments for the reflective invocation or null if an argument of {@code invoke} + * that is expected to be constant isn't */ private Object[] prepareArguments(Invoke invoke, Class<?>[] parameterTypes, ResolvedJavaMethod target, boolean folding) { NodeInputList<ValueNode> arguments = invoke.callTarget().arguments(); @@ -161,8 +146,7 @@ ValueNode argument = tryBoxingElimination(parameterIndex, target, arguments.get(i)); if (folding || MetaUtil.getParameterAnnotation(ConstantNodeParameter.class, parameterIndex, target) != null) { if (!(argument instanceof ConstantNode)) { - throw new NonConstantParameterError("parameter " + parameterIndex + " must be a compile time constant for calling " + invoke.methodCallTarget().targetMethod() + " at " + - sourceLocation(invoke.node()) + ": " + argument); + return null; } ConstantNode constantNode = (ConstantNode) argument; Constant constant = constantNode.asConstant();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetIntrinsificationVerificationPhase.java Tue Mar 12 11:38:52 2013 +0100 @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * 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.graal.snippets; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.graph.Node.NodeIntrinsic; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.java.*; +import com.oracle.graal.phases.*; +import com.oracle.graal.snippets.Snippet.Fold; + +/** + * Checks that a graph contains no calls to {@link NodeIntrinsic} or {@link Fold} methods. + */ +public class SnippetIntrinsificationVerificationPhase extends Phase { + + public static boolean verify(StructuredGraph graph) { + new SnippetIntrinsificationVerificationPhase().apply(graph); + return true; + } + + @Override + protected void run(StructuredGraph graph) { + for (Invoke i : graph.getInvokes()) { + if (i.callTarget() instanceof MethodCallTargetNode) { + checkInvoke(i); + } + } + } + + private static void checkInvoke(Invoke invoke) { + ResolvedJavaMethod target = invoke.methodCallTarget().targetMethod(); + NodeIntrinsic intrinsic = target.getAnnotation(Node.NodeIntrinsic.class); + if (intrinsic != null) { + throw new GraalInternalError("Illegal call to node intrinsic in " + invoke.graph() + ": " + invoke); + } else if (target.getAnnotation(Fold.class) != null) { + throw new GraalInternalError("Illegal call to foldable method in " + invoke.graph() + ": " + invoke); + } + } +}
--- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetTemplate.java Tue Mar 12 11:38:24 2013 +0100 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetTemplate.java Tue Mar 12 11:38:52 2013 +0100 @@ -36,6 +36,7 @@ import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.java.*; +import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; import com.oracle.graal.nodes.util.*; import com.oracle.graal.phases.common.*; @@ -282,11 +283,12 @@ Debug.dump(snippetCopy, "Before specialization"); if (!replacements.isEmpty()) { // Do deferred intrinsification of node intrinsics - new SnippetIntrinsificationPhase(runtime, new BoxingMethodPool(runtime), false).apply(snippetCopy); + new SnippetIntrinsificationPhase(runtime, new BoxingMethodPool(runtime)).apply(snippetCopy); new WordTypeRewriterPhase(runtime, target.wordKind).apply(snippetCopy); new CanonicalizerPhase(runtime, assumptions, 0, null).apply(snippetCopy); } + assert SnippetIntrinsificationVerificationPhase.verify(snippetCopy); // Gather the template parameters parameters = new HashMap<>(); @@ -628,10 +630,9 @@ * @param runtime * @param replacee the node that will be replaced * @param replacer object that replaces the usages of {@code replacee} - * @param lastFixedNode the CFG of the snippet is inserted after this node * @param args the arguments to be bound to the flattened positional parameters of the snippet */ - public void instantiate(MetaAccessProvider runtime, FloatingNode replacee, UsageReplacer replacer, FixedWithNextNode lastFixedNode, SnippetTemplate.Arguments args) { + public void instantiate(MetaAccessProvider runtime, FloatingNode replacee, UsageReplacer replacer, LoweringTool tool, SnippetTemplate.Arguments args) { // Inline the snippet nodes, replacing parameters with the given args in the process String name = snippet.name == null ? "{copy}" : snippet.name + "{copy}"; @@ -643,7 +644,8 @@ Map<Node, Node> duplicates = replaceeGraph.addDuplicates(nodes, replacements); Debug.dump(replaceeGraph, "After inlining snippet %s", snippetCopy.method()); - assert lastFixedNode != null : replaceeGraph; + FixedWithNextNode lastFixedNode = tool.lastFixedNode(); + assert lastFixedNode != null && lastFixedNode.isAlive() : replaceeGraph; FixedNode next = lastFixedNode.next(); lastFixedNode.setNext(null); FixedNode firstCFGNodeDuplicate = (FixedNode) duplicates.get(firstCFGNode); @@ -672,10 +674,14 @@ assert returnValue != null || replacee.usages().isEmpty(); replacer.replace(replacee, returnValue); + tool.setLastFixedNode(null); Node returnDuplicate = duplicates.get(returnNode); if (returnDuplicate.isAlive()) { returnDuplicate.clearInputs(); returnDuplicate.replaceAndDelete(next); + if (next != null && next.predecessor() instanceof FixedWithNextNode) { + tool.setLastFixedNode((FixedWithNextNode) next.predecessor()); + } } Debug.dump(replaceeGraph, "After lowering %s with %s", replacee, this);
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/SimpleLanguage.atg Tue Mar 12 11:38:24 2013 +0100 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/SimpleLanguage.atg Tue Mar 12 11:38:52 2013 +0100 @@ -131,16 +131,16 @@ | NumericLiteral<out result> | - Ternary<out result> + Ternary<out result> | "(" Expression<out result> ")" ) . -Ternary<out TypedNode result> (. TypedNode condition, thenPart, elsePart; .) +Ternary<out TypedNode result> (. TypedNode condition, thenPart, elsePart; .) = "#" Expression<out condition> "?" Expression<out thenPart> ":" Expression<out elsePart> - (. result = factory.createTernary(condition, thenPart, elsePart); .) + (. result = factory.createTernary(condition, thenPart, elsePart); .) . TimeRef<out TypedNode result>
--- a/make/Makefile Tue Mar 12 11:38:24 2013 +0100 +++ b/make/Makefile Tue Mar 12 11:38:52 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 @@ -84,10 +84,12 @@ ALT_OUT= endif +# Directory for shared code (e.g. graal.jar) +SHARED_DIR=$(OUTPUTDIR)/shared + # 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 +170,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=$@ \ @@ -193,7 +190,7 @@ $(MAKE) VM_TARGET=$@ generic_buildgraal $(ALT_OUT) # Build compiler1 (client) rule, different for platforms -generic_build1: +generic_build1: buildshared $(MKDIR) -p $(OUTPUTDIR) ifeq ($(OSNAME),windows) ifeq ($(ARCH_DATA_MODEL), 32) @@ -214,7 +211,7 @@ endif # Build compiler2 (server) rule, different for platforms -generic_build2: +generic_build2: buildshared $(MKDIR) -p $(OUTPUTDIR) ifeq ($(OSNAME),windows) $(CD) $(OUTPUTDIR); \ @@ -230,24 +227,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); \ @@ -281,12 +260,16 @@ @$(ECHO) "Error: trying to build a minimal target but JVM_VARIANT_MINIMAL1 is not true." endif -generic_buildgraal: +generic_buildgraal: buildshared $(MKDIR) -p $(OUTPUTDIR) $(CD) $(OUTPUTDIR); \ $(MAKE) -f $(ABS_OS_MAKEFILE) \ $(MAKE_ARGS) $(VM_TARGET) +# Builds code that can be shared among different build flavors +buildshared: + $(REMOTE) $(ANT) -f $(GAMMADIR)/make/build-graal.xml -Dgamma.dir=$(GAMMADIR) -Dshared.dir=$(SHARED_DIR) + # Export file rule generic_export: $(EXPORT_LIST) export_product: @@ -327,13 +310,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 +329,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 +378,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 @@ -426,6 +393,7 @@ # Shared Library ifneq ($(OSNAME),windows) ifeq ($(JVM_VARIANT_SERVER), true) + # C2 $(EXPORT_JRE_LIB_ARCH_DIR)/%.$(LIBRARY_SUFFIX): $(C2_DIR)/%.$(LIBRARY_SUFFIX) $(install-file) $(EXPORT_SERVER_DIR)/%.$(LIBRARY_SUFFIX): $(C2_DIR)/%.$(LIBRARY_SUFFIX) @@ -444,7 +412,27 @@ $(install-file) $(EXPORT_SERVER_DIR)/64/%.diz: $(C2_DIR)/%.diz $(install-file) - endif + + # Graal + $(EXPORT_JRE_LIB_ARCH_DIR)/%.$(LIBRARY_SUFFIX): $(GRAAL_DIR)/%.$(LIBRARY_SUFFIX) + $(install-file) + $(EXPORT_SERVER_DIR)/%.$(LIBRARY_SUFFIX): $(GRAAL_DIR)/%.$(LIBRARY_SUFFIX) + $(install-file) + $(EXPORT_SERVER_DIR)/64/%.$(LIBRARY_SUFFIX): $(GRAAL_DIR)/%.$(LIBRARY_SUFFIX) + $(install-file) + $(EXPORT_JRE_LIB_ARCH_DIR)/%.debuginfo: $(GRAAL_DIR)/%.debuginfo + $(install-file) + $(EXPORT_SERVER_DIR)/%.debuginfo: $(GRAAL_DIR)/%.debuginfo + $(install-file) + $(EXPORT_SERVER_DIR)/64/%.debuginfo: $(GRAAL_DIR)/%.debuginfo + $(install-file) + $(EXPORT_JRE_LIB_ARCH_DIR)/%.diz: $(GRAAL_DIR)/%.diz + $(install-file) + $(EXPORT_SERVER_DIR)/%.diz: $(GRAAL_DIR)/%.diz + $(install-file) + $(EXPORT_SERVER_DIR)/64/%.diz: $(GRAAL_DIR)/%.diz + $(install-file) + endif ifeq ($(JVM_VARIANT_CLIENT), true) $(EXPORT_JRE_LIB_ARCH_DIR)/%.$(LIBRARY_SUFFIX): $(C1_DIR)/%.$(LIBRARY_SUFFIX) $(install-file) @@ -519,7 +507,8 @@ $(EXPORT_LIB_DIR)/%.jar: $(GEN_DIR)/%.jar $(install-file) -$(EXPORT_JRE_LIB_DIR)/%.jar: $(GEN_DIR)/%.jar +# Shared jar files +$(EXPORT_JRE_LIB_DIR)/%.jar: $(SHARED_DIR)/%.jar $(install-file) # Include files (jvmti.h, jvmticmlr.h, jni.h, $(JDK_INCLUDE_SUBDIR)/jni_md.h, jmm.h, jfr.h) @@ -553,7 +542,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 @@ -564,9 +553,9 @@ # clobber clean: clean_build clean_export clean_jdk clean_build: + $(RM) -r $(SHARED_DIR) $(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 +591,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 +666,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 +761,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 \
--- a/make/bsd/makefiles/buildtree.make Tue Mar 12 11:38:24 2013 +0100 +++ b/make/bsd/makefiles/buildtree.make Tue Mar 12 11:38:52 2013 +0100 @@ -354,7 +354,7 @@ $(BUILDTREE_COMMENT); \ [ -n "$$JAVA_HOME" ] && { echo ": \$${JAVA_HOME:=$${JAVA_HOME}}"; }; \ { \ - echo "CLASSPATH=$${CLASSPATH:+$$CLASSPATH:}.:\$${JAVA_HOME}/jre/lib/rt.jar:\$${JAVA_HOME}/jre/lib/i18n.jar"; \ + echo "CLASSPATH=$${CLASSPATH:+$$CLASSPATH:}.:\$${JAVA_HOME}/jre/lib/rt.jar:$(OUTPUTDIR)/shared/graal.jar:\$${JAVA_HOME}/jre/lib/i18n.jar"; \ } | sed s:$${JAVA_HOME:--------}:\$${JAVA_HOME}:g; \ echo "HOTSPOT_BUILD_USER=\"$${LOGNAME:-$$USER} in `basename $(GAMMADIR)`\""; \ echo "export JAVA_HOME CLASSPATH HOTSPOT_BUILD_USER"; \
--- a/make/bsd/makefiles/defs.make Tue Mar 12 11:38:24 2013 +0100 +++ b/make/bsd/makefiles/defs.make Tue Mar 12 11:38:52 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)
--- a/make/bsd/makefiles/dtrace.make Tue Mar 12 11:38:24 2013 +0100 +++ b/make/bsd/makefiles/dtrace.make Tue Mar 12 11:38:52 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:
--- a/make/bsd/makefiles/mapfile-vers-debug Tue Mar 12 11:38:24 2013 +0100 +++ b/make/bsd/makefiles/mapfile-vers-debug Tue Mar 12 11:38:52 2013 +0100 @@ -188,6 +188,7 @@ JVM_IsSilentCompiler; JVM_IsSupportedJNIVersion; JVM_IsThreadAlive; + JVM_IsVMGeneratedMethodIx; JVM_LatestUserDefinedLoader; JVM_Listen; JVM_LoadClass0;
--- a/make/bsd/makefiles/mapfile-vers-product Tue Mar 12 11:38:24 2013 +0100 +++ b/make/bsd/makefiles/mapfile-vers-product Tue Mar 12 11:38:52 2013 +0100 @@ -188,6 +188,7 @@ JVM_IsSilentCompiler; JVM_IsSupportedJNIVersion; JVM_IsThreadAlive; + JVM_IsVMGeneratedMethodIx; JVM_LatestUserDefinedLoader; JVM_Listen; JVM_LoadClass0;
--- a/make/bsd/makefiles/minimal1.make Tue Mar 12 11:38:24 2013 +0100 +++ b/make/bsd/makefiles/minimal1.make Tue Mar 12 11:38:52 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
--- a/make/bsd/makefiles/vm.make Tue Mar 12 11:38:24 2013 +0100 +++ b/make/bsd/makefiles/vm.make Tue Mar 12 11:38:52 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
--- a/make/bsd/makefiles/wb.make Tue Mar 12 11:38:24 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 $@ -
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/build-graal.xml Tue Mar 12 11:38:52 2013 +0100 @@ -0,0 +1,55 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + 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. Oracle designates this + particular file as subject to the "Classpath" exception as provided + by Oracle in the LICENSE file that accompanied this code. + + This code is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + version 2 for more details (a copy is included in the LICENSE file that + accompanied this code). + + You should have received a copy of the GNU General Public License version + 2 along with this work; if not, write to the Free Software Foundation, + Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + + Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + or visit www.oracle.com if you need additional information or have any + questions. +--> + +<project name="graal" basedir="." default="main"> + <property name="src.dir" value="${gamma.dir}/graal"/> + <property name="classes.dir" value="${shared.dir}/graal"/> + <property name="jar.dir" value="${shared.dir}"/> + <property name="jar.file" value="${jar.dir}/graal.jar"/> + + <target name="main" depends="jar"/> + + <target name="compile"> + <mkdir dir="${classes.dir}"/> + <javac srcdir="${src.dir}" destdir="${classes.dir}" debug="on"> + <include name="com.oracle.graal.*/**"/> + <exclude name="com.oracle.graal.test/**"/> + <exclude name="com.oracle.graal.*.test/**"/> + <exclude name="com.oracle.graal.jtt/**"/> + <compilerarg value="-XDignore.symbol.file"/> + </javac> + </target> + + <target name="jar" depends="compile"> + <mkdir dir="${jar.dir}"/> + <jar destfile="${jar.file}" basedir="${classes.dir}"/> + </target> + + <target name="clean"> + <delete dir="${classes.dir}"/> + <delete file="${jar.file}"/> + </target> +</project>
--- a/make/defs.make Tue Mar 12 11:38:24 2013 +0100 +++ b/make/defs.make Tue Mar 12 11:38:52 2013 +0100 @@ -236,6 +236,33 @@ JDK_IMAGE_DIR=$(ALT_JDK_IMAGE_DIR) endif +# Utilities ant +ifeq ($(PLATFORM), windows) + ifeq ($(ANT_HOME),) + ANT_HOME := $(call DirExists,$(JDK_DEVTOOLS_DIR)/share/ant/latest,,) + endif +endif + +# There are few problems with ant we need to workaround: +# 1) ant is using temporary directory java.io.tmpdir +# However, this directory is not unique enough and two separate ant processes +# can easily end up using the exact same temp directory. This may lead to weird build failures +# To workaround this we will define tmp dir explicitly +# 2) ant attempts to detect JDK location based on java.exe location +# This is fragile as developer may have JRE first on the PATH. +# To workaround this we will specify JAVA_HOME explicitly +# 3) Sometimes we need to run ant with the boot jdk, sometimes with the import +# jdk, sometimes with the jdk we are building (see deploy repo). + +ANT_TMPDIR = $(OUTPUTDIR)/tmp +ANT_WORKAROUNDS = ANT_OPTS=-Djava.io.tmpdir='$(ANT_TMPDIR)' + +ifeq ($(ANT_HOME),) + ANT = $(ANT_WORKAROUNDS) JAVA_HOME='$(BOOTDIR)' ant +else + ANT = $(ANT_WORKAROUNDS) JAVA_HOME='$(BOOTDIR)' $(ANT_HOME)/bin/ant +endif + # The platform dependent defs.make defines platform specific variable such # as ARCH, EXPORT_LIST etc. We must place the include here after BOOTDIR is defined. include $(GAMMADIR)/make/$(OSNAME)/makefiles/defs.make @@ -336,6 +363,7 @@ EXPORT_LIST += $(EXPORT_INCLUDE_DIR)/jni.h EXPORT_LIST += $(EXPORT_INCLUDE_DIR)/$(JDK_INCLUDE_SUBDIR)/jni_md.h EXPORT_LIST += $(EXPORT_INCLUDE_DIR)/jmm.h +EXPORT_LIST += $(EXPORT_JRE_LIB_DIR)/graal.jar # By default, run Queens test after building TEST_IN_BUILD ?= true
--- a/make/excludeSrc.make Tue Mar 12 11:38:24 2013 +0100 +++ b/make/excludeSrc.make Tue Mar 12 11:38:52 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)
--- a/make/hotspot_version Tue Mar 12 11:38:24 2013 +0100 +++ b/make/hotspot_version Tue Mar 12 11:38:52 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
--- a/make/linux/makefiles/buildtree.make Tue Mar 12 11:38:24 2013 +0100 +++ b/make/linux/makefiles/buildtree.make Tue Mar 12 11:38:52 2013 +0100 @@ -347,7 +347,7 @@ $(BUILDTREE_COMMENT); \ [ -n "$$JAVA_HOME" ] && { echo ": \$${JAVA_HOME:=$${JAVA_HOME}}"; }; \ { \ - echo "CLASSPATH=$${CLASSPATH:+$$CLASSPATH:}.:\$${JAVA_HOME}/jre/lib/rt.jar:\$${JAVA_HOME}/jre/lib/i18n.jar"; \ + echo "CLASSPATH=$${CLASSPATH:+$$CLASSPATH:}.:\$${JAVA_HOME}/jre/lib/rt.jar:$(OUTPUTDIR)/shared/graal.jar:\$${JAVA_HOME}/jre/lib/i18n.jar"; \ } | sed s:$${JAVA_HOME:--------}:\$${JAVA_HOME}:g; \ echo "HOTSPOT_BUILD_USER=\"$${LOGNAME:-$$USER} in `basename $(GAMMADIR)`\""; \ echo "export JAVA_HOME CLASSPATH HOTSPOT_BUILD_USER"; \
--- a/make/linux/makefiles/defs.make Tue Mar 12 11:38:24 2013 +0100 +++ b/make/linux/makefiles/defs.make Tue Mar 12 11:38:52 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)
--- a/make/linux/makefiles/mapfile-vers-debug Tue Mar 12 11:38:24 2013 +0100 +++ b/make/linux/makefiles/mapfile-vers-debug Tue Mar 12 11:38:52 2013 +0100 @@ -184,6 +184,7 @@ JVM_IsSilentCompiler; JVM_IsSupportedJNIVersion; JVM_IsThreadAlive; + JVM_IsVMGeneratedMethodIx; JVM_LatestUserDefinedLoader; JVM_Listen; JVM_LoadClass0;
--- a/make/linux/makefiles/mapfile-vers-product Tue Mar 12 11:38:24 2013 +0100 +++ b/make/linux/makefiles/mapfile-vers-product Tue Mar 12 11:38:52 2013 +0100 @@ -184,6 +184,7 @@ JVM_IsSilentCompiler; JVM_IsSupportedJNIVersion; JVM_IsThreadAlive; + JVM_IsVMGeneratedMethodIx; JVM_LatestUserDefinedLoader; JVM_Listen; JVM_LoadClass0;
--- a/make/linux/makefiles/minimal1.make Tue Mar 12 11:38:24 2013 +0100 +++ b/make/linux/makefiles/minimal1.make Tue Mar 12 11:38:52 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
--- a/make/linux/makefiles/vm.make Tue Mar 12 11:38:24 2013 +0100 +++ b/make/linux/makefiles/vm.make Tue Mar 12 11:38:52 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
--- a/make/linux/makefiles/wb.make Tue Mar 12 11:38:24 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 $@ -
--- a/make/sa.files Tue Mar 12 11:38:24 2013 +0100 +++ b/make/sa.files Tue Mar 12 11:38:52 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 \
--- a/make/solaris/Makefile Tue Mar 12 11:38:24 2013 +0100 +++ b/make/solaris/Makefile Tue Mar 12 11:38:52 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
--- a/make/solaris/makefiles/buildtree.make Tue Mar 12 11:38:24 2013 +0100 +++ b/make/solaris/makefiles/buildtree.make Tue Mar 12 11:38:52 2013 +0100 @@ -336,7 +336,7 @@ $(BUILDTREE_COMMENT); \ [ -n "$$JAVA_HOME" ] && { echo ": \$${JAVA_HOME:=$${JAVA_HOME}}"; }; \ { \ - echo "CLASSPATH=$${CLASSPATH:+$$CLASSPATH:}.:\$${JAVA_HOME}/jre/lib/rt.jar:\$${JAVA_HOME}/jre/lib/i18n.jar"; \ + echo "CLASSPATH=$${CLASSPATH:+$$CLASSPATH:}.:\$${JAVA_HOME}/jre/lib/rt.jar:$(OUTPUTDIR)/shared/graal.jar:\$${JAVA_HOME}/jre/lib/i18n.jar"; \ } | sed s:$${JAVA_HOME:--------}:\$${JAVA_HOME}:g; \ echo "HOTSPOT_BUILD_USER=\"$${LOGNAME:-$$USER} in `basename $(GAMMADIR)`\""; \ echo "export JAVA_HOME LD_LIBRARY_PATH CLASSPATH HOTSPOT_BUILD_USER"; \
--- a/make/solaris/makefiles/defs.make Tue Mar 12 11:38:24 2013 +0100 +++ b/make/solaris/makefiles/defs.make Tue Mar 12 11:38:52 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
--- a/make/solaris/makefiles/dtrace.make Tue Mar 12 11:38:24 2013 +0100 +++ b/make/solaris/makefiles/dtrace.make Tue Mar 12 11:38:52 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:
--- a/make/solaris/makefiles/kernel.make Tue Mar 12 11:38:24 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
--- a/make/solaris/makefiles/mapfile-vers Tue Mar 12 11:38:24 2013 +0100 +++ b/make/solaris/makefiles/mapfile-vers Tue Mar 12 11:38:52 2013 +0100 @@ -184,6 +184,7 @@ JVM_IsSilentCompiler; JVM_IsSupportedJNIVersion; JVM_IsThreadAlive; + JVM_IsVMGeneratedMethodIx; JVM_LatestUserDefinedLoader; JVM_Listen; JVM_LoadClass0;
--- a/make/solaris/makefiles/vm.make Tue Mar 12 11:38:24 2013 +0100 +++ b/make/solaris/makefiles/vm.make Tue Mar 12 11:38:52 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
--- a/make/solaris/makefiles/wb.make Tue Mar 12 11:38:24 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 $@ -
--- a/make/windows/build.bat Tue Mar 12 11:38:24 2013 +0100 +++ b/make/windows/build.bat Tue Mar 12 11:38:52 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
--- a/make/windows/create_obj_files.sh Tue Mar 12 11:38:24 2013 +0100 +++ b/make/windows/create_obj_files.sh Tue Mar 12 11:38:52 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}" ;;
--- a/make/windows/makefiles/debug.make Tue Mar 12 11:38:24 2013 +0100 +++ b/make/windows/makefiles/debug.make Tue Mar 12 11:38:52 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
--- a/make/windows/makefiles/defs.make Tue Mar 12 11:38:24 2013 +0100 +++ b/make/windows/makefiles/defs.make Tue Mar 12 11:38:52 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)
--- a/make/windows/makefiles/fastdebug.make Tue Mar 12 11:38:24 2013 +0100 +++ b/make/windows/makefiles/fastdebug.make Tue Mar 12 11:38:52 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
--- a/make/windows/makefiles/product.make Tue Mar 12 11:38:24 2013 +0100 +++ b/make/windows/makefiles/product.make Tue Mar 12 11:38:52 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
--- a/make/windows/makefiles/projectcreator.make Tue Mar 12 11:38:24 2013 +0100 +++ b/make/windows/makefiles/projectcreator.make Tue Mar 12 11:38:52 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) \
--- a/make/windows/makefiles/vm.make Tue Mar 12 11:38:24 2013 +0100 +++ b/make/windows/makefiles/vm.make Tue Mar 12 11:38:52 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
--- a/make/windows/makefiles/wb.make Tue Mar 12 11:38:24 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) -
--- a/mx/commands.py Tue Mar 12 11:38:24 2013 +0100 +++ b/mx/commands.py Tue Mar 12 11:38:52 2013 +0100 @@ -77,6 +77,8 @@ """ +_minVersion = mx.JavaVersion('1.7.0_04') + def _chmodDir(chmodFlags, dirname, fnames): os.chmod(dirname, chmodFlags) for name in fnames: @@ -91,7 +93,7 @@ if opts.native: os.environ.update(ARCH_DATA_MODEL='64', LANG='C', HOTSPOT_BUILD_JOBS='16') mx.run([mx.gmake_cmd(), 'clean'], cwd=join(_graal_home, 'make')) - jdks = join(_graal_home, 'jdk' + mx.java().version) + jdks = join(_graal_home, 'jdk' + str(mx.java().version)) if exists(jdks): shutil.rmtree(jdks) @@ -318,7 +320,7 @@ """ Get the JDK into which Graal is installed, creating it first if necessary. """ - jdk = join(_graal_home, 'jdk' + mx.java().version, build) + jdk = join(_graal_home, 'jdk' + str(mx.java().version), build) jdkContents = ['bin', 'include', 'jre', 'lib'] if (exists(join(jdk, 'db'))): jdkContents.append('db') @@ -371,8 +373,24 @@ else: if not exists(jdk): mx.abort('The ' + build + ' VM has not been created - run \'mx clean; mx build ' + build + '\'') + + _installGraalJarInJdks(mx.distribution('GRAAL')) + return jdk +def _installGraalJarInJdks(graalDist): + graalJar = graalDist.path + jdks = join(_graal_home, 'jdk' + str(mx.java().version)) + if exists(jdks): + for e in os.listdir(jdks): + jreLibDir = join(jdks, e, 'jre', 'lib') + if exists(jreLibDir): + # do a copy and then a move to get atomic updating (on Unix) of graal.jar in the JRE + fd, tmp = tempfile.mkstemp(suffix='', prefix='graal.jar', dir=jreLibDir) + shutil.copyfile(graalJar, tmp) + os.close(fd) + shutil.move(tmp, join(jreLibDir, 'graal.jar')) + # run a command in the windows SDK Debug Shell def _runInDebugShell(cmd, workingDir, logFile=None, findInOutput=None, respondTo={}): newLine = os.linesep @@ -435,7 +453,7 @@ """print the JDK directory selected for the 'vm' command""" build = _vmbuild if _vmSourcesAvailable else 'product' - print join(_graal_home, 'jdk' + mx.java().version, build) + print join(_graal_home, 'jdk' + str(mx.java().version), build) def build(args, vm=None): """build the VM binary @@ -486,25 +504,6 @@ if not 'Xusage.txt' in line: sys.stderr.write(line + os.linesep) - # Check that the declaration of graal_projects in arguments.cpp is up to date - argumentsCpp = join(_graal_home, 'src', 'share', 'vm', 'runtime', 'arguments.cpp') - assert exists(argumentsCpp), 'File does not exist: ' + argumentsCpp - with open(argumentsCpp) as fp: - source = fp.read(); - decl = 'const char* graal_projects[] = {' - start = source.find(decl) - assert start != -1, 'Could not find "' + decl + '" in ' + fp.name - end = source.find('};', start) - assert end != -1, 'Could not find "' + decl + '" ... "};" in ' + fp.name - actual = frozenset(re.findall(r'"([^"]+)"', source[start + len(decl):end])) - expected = frozenset([p.name for p in mx.project('com.oracle.graal.hotspot.' + _arch()).all_deps([], False)]) - missing = expected - actual - extra = actual - expected - if len(missing) != 0: - mx.abort(fp.name + ':' + str(source[:start].count('\n') + 1) + ': add missing project(s) to declaration:\n ' + '\n '.join(missing)) - if len(extra) != 0: - mx.abort(fp.name + ':' + str(source[:start].count('\n') + 1) + ': remove project(s) from declaration:\n ' + '\n '.join(extra)) - # Check if a build really needs to be done timestampFile = join(vmDir, '.build-timestamp') if opts2.force or not exists(timestampFile): @@ -654,6 +653,7 @@ args = ['-javaagent:' + jacocoagent.get_path(True) + '=' + ','.join([k + '=' + v for k, v in agentOptions.items()])] + args if '-d64' not in args: args = ['-d64'] + args + exe = join(jdk, 'bin', mx.exe_suffix('java')) dbg = _native_dbg.split() if _native_dbg is not None else [] return mx.run(dbg + [exe, '-' + vm] + args, nonZeroIsFatal=nonZeroIsFatal, out=out, err=err, cwd=cwd, timeout=timeout) @@ -784,11 +784,22 @@ if mx.eclipseformat(['-e', eclipse_exe]) != 0: t.abort('Formatter modified files - run "mx eclipseformat", check in changes and repush') tasks.append(t.stop()) + + t = Task('Canonicalization Check') + mx.log(time.strftime('%d %b %Y %H:%M:%S - Ensuring mx/projects files are canonicalized...')) + if mx.canonicalizeprojects([]) != 0: + t.abort('Rerun "mx canonicalizeprojects" and check-in the modified mx/projects files.') + tasks.append(t.stop()) t = Task('BuildJava') build(['--no-native', '--jdt-warning-as-error']) tasks.append(t.stop()) + t = Task('Checkstyle') + if mx.checkstyle([]) != 0: + t.abort('Checkstyle warnings were found') + tasks.append(t.stop()) + if exists('jacoco.exec'): os.unlink('jacoco.exec') @@ -796,10 +807,9 @@ _jacoco = 'append' else: _jacoco = 'off' - t = Task('BuildHotSpotGraal: fastdebug,product') - buildvms(['--vms', 'graal', '--builds', 'fastdebug,product']) + buildvms(['--vms', 'graal,server', '--builds', 'fastdebug,product']) tasks.append(t.stop()) _vmbuild = 'fastdebug' @@ -808,9 +818,12 @@ tasks.append(t.stop()) _vmbuild = 'product' - t = Task('UnitTests:product') + originalVm = _vm + _vm = 'server' # hosted mode + t = Task('UnitTests:hosted-product') unittest([]) tasks.append(t.stop()) + _vm = originalVm for vmbuild in ['fastdebug', 'product']: for test in sanitycheck.getDacapos(level=sanitycheck.SanityCheckLevel.Gate, gateBuildLevel=vmbuild): @@ -824,17 +837,6 @@ _jacoco = 'off' - t = Task('Checkstyle') - if mx.checkstyle([]) != 0: - t.abort('Checkstyle warnings were found') - tasks.append(t.stop()) - - t = Task('Canonicalization Check') - mx.log(time.strftime('%d %b %Y %H:%M:%S - Ensuring mx/projects files are canonicalized...')) - if mx.canonicalizeprojects([]) != 0: - t.abort('Rerun "mx canonicalizeprojects" and check-in the modified mx/projects files.') - tasks.append(t.stop()) - t = Task('CleanAndBuildGraalVisualizer') mx.run(['ant', '-f', join(_graal_home, 'visualizer', 'build.xml'), '-q', 'clean', 'build']) tasks.append(t.stop()) @@ -1016,6 +1018,15 @@ benchArgs.remove(args[itIdx+1]) vm = _vm; sanitycheck.getSPECjvm2008(benchArgs, skipCheck, skipValid, wt, it).bench(vm, opts=vmArgs) + +def specjbb2013(args): + """runs the composite SPECjbb2013 benchmark + + All options begining with - will be passed to the vm""" + benchArgs = [a for a in args if a[0] != '-'] + vmArgs = [a for a in args if a[0] == '-'] + vm = _vm; + sanitycheck.getSPECjbb2013(benchArgs).bench(vm, opts=vmArgs) def hsdis(args, copyToDir=None): """download the hsdis library @@ -1094,20 +1105,6 @@ mx.abort('jacocoreport takes only one argument : an output directory') mx.run_java(['-jar', jacocoreport.get_path(True), '-in', 'jacoco.exec', '-g', join(_graal_home, 'graal'), out]) -def jar(args): - parser = ArgumentParser(prog='mx jar'); - parser.add_argument('projects', nargs=REMAINDER, metavar='projects...') - args = parser.parse_args(args) - - if not args.projects: - mx.abort('Please specify at least one project to jar.') - - for pname in args.projects: - p = mx.project(pname, fatalIfMissing=True) - outputDir = p.output_dir() - targetJar = join(p.dir, p.name + '.jar') - mx.jar(targetJar, [outputDir]) - def site(args): """create a website containing javadoc and the project dependency graph""" @@ -1133,8 +1130,8 @@ 'jdkhome': [jdkhome, ''], 'dacapo': [dacapo, '[[n] benchmark] [VM options|@DaCapo options]'], 'scaladacapo': [scaladacapo, '[[n] benchmark] [VM options|@Scala DaCapo options]'], - 'specjvm2008': [specjvm2008, '[VM options|@specjvm2008 options]'], - 'jar': [jar, '[-options]'], + 'specjvm2008': [specjvm2008, '[VM options|specjvm2008 options (-v, -ikv, -ict, -wt, -it)]'], + 'specjbb2013': [specjbb2013, '[VM options]'], #'example': [example, '[-v] example names...'], 'gate' : [gate, '[-options]'], 'gv' : [gv, ''], @@ -1168,23 +1165,10 @@ mx.commands.update(commands) -def mx_post_parse_cmd_line(opts): - version = mx.java().version.split('-')[0] - parts = version.split('.') - assert len(parts) >= 2 - assert parts[0] == '1' - major = int(parts[1]) - minor = 0 - update = 0 - if len(parts) >= 3: - minorParts = parts[2].split('_') - if len(minorParts) >= 1: - minor = int(minorParts[0]) - if len(minorParts) >= 2: - update = int(minorParts[1]) - - if (not major >= 7) or (major == 7 and minor == 0 and not update >= 4) : - mx.abort('Requires Java version 1.7.0_04 or greater, got version ' + version) +def mx_post_parse_cmd_line(opts):# + # TODO _minVersion check could probably be part of a Suite in mx? + if (mx.java().version < _minVersion) : + mx.abort('Requires Java version ' + str(_minVersion) + ' or greater, got version ' + str(mx.java().version)) if (_vmSourcesAvailable): if hasattr(opts, 'vm') and opts.vm is not None: @@ -1199,3 +1183,5 @@ _jacoco = opts.jacoco global _native_dbg _native_dbg = opts.native_dbg + + mx.distribution('GRAAL').add_update_listener(_installGraalJarInJdks)
--- a/mx/projects Tue Mar 12 11:38:24 2013 +0100 +++ b/mx/projects Tue Mar 12 11:38:52 2013 +0100 @@ -22,6 +22,9 @@ library@DACAPO_SCALA@path=lib/dacapo-scala-0.1.0-20120216.jar library@DACAPO_SCALA@urls=http://repo.scalabench.org/snapshots/org/scalabench/benchmarks/scala-benchmark-suite/0.1.0-SNAPSHOT/scala-benchmark-suite-0.1.0-20120216.103539-3.jar +distribution@GRAAL@path=graal.jar +distribution@GRAAL@dependencies=com.oracle.graal.hotspot.amd64,com.oracle.graal.hotspot.sparc + # graal.api.runtime project@com.oracle.graal.api.runtime@subDir=graal project@com.oracle.graal.api.runtime@sourceDirs=src @@ -235,6 +238,13 @@ project@com.oracle.graal.compiler.amd64@checkstyle=com.oracle.graal.graph project@com.oracle.graal.compiler.amd64@javaCompliance=1.7 +# graal.compiler.amd64.test +project@com.oracle.graal.compiler.amd64.test@subDir=graal +project@com.oracle.graal.compiler.amd64.test@sourceDirs=src +project@com.oracle.graal.compiler.amd64.test@dependencies=com.oracle.graal.compiler.test +project@com.oracle.graal.compiler.amd64.test@checkstyle=com.oracle.graal.graph +project@com.oracle.graal.compiler.amd64.test@javaCompliance=1.7 + # graal.compiler.ptx project@com.oracle.graal.compiler.ptx@subDir=graal project@com.oracle.graal.compiler.ptx@sourceDirs=src @@ -245,7 +255,7 @@ # graal.compiler.ptx.test project@com.oracle.graal.compiler.ptx.test@subDir=graal project@com.oracle.graal.compiler.ptx.test@sourceDirs=src -project@com.oracle.graal.compiler.ptx.test@dependencies=com.oracle.graal.compiler.ptx,com.oracle.graal.compiler.test +project@com.oracle.graal.compiler.ptx.test@dependencies=com.oracle.graal.compiler.ptx,com.oracle.graal.compiler.test,com.oracle.graal.ptx project@com.oracle.graal.compiler.ptx.test@checkstyle=com.oracle.graal.graph project@com.oracle.graal.compiler.ptx.test@javaCompliance=1.7 @@ -328,7 +338,7 @@ # graal.asm.ptx project@com.oracle.graal.asm.ptx@subDir=graal project@com.oracle.graal.asm.ptx@sourceDirs=src -project@com.oracle.graal.asm.ptx@dependencies=com.oracle.graal.asm,com.oracle.graal.ptx +project@com.oracle.graal.asm.ptx@dependencies=com.oracle.graal.asm project@com.oracle.graal.asm.ptx@checkstyle=com.oracle.graal.graph project@com.oracle.graal.asm.ptx@javaCompliance=1.7
--- a/mx/sanitycheck.py Tue Mar 12 11:38:24 2013 +0100 +++ b/mx/sanitycheck.py Tue Mar 12 11:38:52 2013 +0100 @@ -119,7 +119,7 @@ success = re.compile(r"org.spec.jbb.controller: Run finished", re.MULTILINE) matcherMax = ValuesMatcher(jops, {'group' : 'SPECjbb2013', 'name' : 'max', 'score' : '<max>'}) matcherCritical = ValuesMatcher(jops, {'group' : 'SPECjbb2013', 'name' : 'critical', 'score' : '<critical>'}) - return Test("SPECjbb2013", ['-jar', 'specjbb2013.jar', '-m', 'composite'] + benchArgs, [success], [], [matcherCritical, matcherMax], vmOpts=['-Xms7g', '-XX:+UseSerialGC', '-XX:-UseCompressedOops'], defaultCwd=specjbb2013) + return Test("SPECjbb2013", ['-jar', 'specjbb2013.jar', '-m', 'composite'] + benchArgs, [success], [], [matcherCritical, matcherMax], vmOpts=['-Xmx6g', '-Xms6g', '-Xmn3g', '-XX:+UseParallelOldGC', '-XX:-UseAdaptiveSizePolicy', '-XX:-UseBiasedLocking', '-XX:-UseCompressedOops'], defaultCwd=specjbb2013) def getSPECjvm2008(benchArgs = [], skipCheck=False, skipKitValidation=False, warmupTime=None, iterationTime=None): @@ -270,9 +270,12 @@ if len(valueMaps) == 0: return False - assert len(valueMaps) == 1, 'Test matchers should not return more than one record' - - record = valueMaps[0] + record = {} + for valueMap in valueMaps: + for key, value in valueMap.items(): + if record.has_key(key) and record[key] != value: + mx.abort('Inconsistant values returned by test machers : ' + str(valueMaps)) + record[key] = value jvmErrorFile = record.get('jvmError') if jvmErrorFile:
--- a/mxtool/mx.py Tue Mar 12 11:38:24 2013 +0100 +++ b/mxtool/mx.py Tue Mar 12 11:38:52 2013 +0100 @@ -143,12 +143,36 @@ _projects = dict() _libs = dict() +_dists = dict() _suites = dict() _mainSuite = None _opts = None _java = None """ +A distribution is a jar or zip file containing the output from one or more Java projects. +""" +class Distribution: + def __init__(self, suite, name, path, deps): + self.suite = suite + self.name = name + self.path = path.replace('/', os.sep) + if not isabs(self.path): + self.path = join(suite.dir, self.path) + self.deps = deps + self.update_listeners = set() + + def __str__(self): + return self.name + + def add_update_listener(self, listener): + self.update_listeners.add(listener) + + def notify_updated(self): + for l in self.update_listeners: + l(self) + +""" A dependency is a library or project specified in a suite. """ class Dependency: @@ -416,6 +440,7 @@ self.dir = d self.projects = [] self.libs = [] + self.dists = [] self.includes = [] self.commands = None self.primary = primary @@ -427,6 +452,7 @@ def _load_projects(self, mxDir): libsMap = dict() projsMap = dict() + distsMap = dict() projectsFile = join(mxDir, 'projects') if not exists(projectsFile): return @@ -447,8 +473,10 @@ m = projsMap elif kind == 'library': m = libsMap + elif kind == 'distribution': + m = distsMap else: - abort('Property name does not start with "project@" or "library@": ' + key) + abort('Property name does not start with "project@", "library@" or "distribution@": ' + key) attrs = m.get(name) if attrs is None: @@ -494,6 +522,13 @@ l.__dict__.update(attrs) self.libs.append(l) + for name, attrs in distsMap.iteritems(): + path = attrs.pop('path') + deps = pop_list(attrs, 'dependencies') + d = Distribution(self, name, path, deps) + d.__dict__.update(attrs) + self.dists.append(d) + def _load_commands(self, mxDir): commands = join(mxDir, 'commands.py') if exists(commands): @@ -536,8 +571,6 @@ def _post_init(self, opts): mxDir = join(self.dir, 'mx') self._load_projects(mxDir) - if hasattr(self, 'mx_post_parse_cmd_line'): - self.mx_post_parse_cmd_line(opts) for p in self.projects: existing = _projects.get(p.name) if existing is not None: @@ -549,6 +582,13 @@ if existing is not None: abort('cannot redefine library ' + l.name) _libs[l.name] = l + for d in self.dists: + existing = _dists.get(l.name) + if existing is not None: + abort('cannot redefine distribution ' + d.name) + _dists[d.name] = d + if hasattr(self, 'mx_post_parse_cmd_line'): + self.mx_post_parse_cmd_line(opts) class XMLElement(xml.dom.minidom.Element): def writexml(self, writer, indent="", addindent="", newl=""): @@ -653,6 +693,16 @@ """ return _projects.values() +def distribution(name, fatalIfMissing=True): + """ + Get the distribution for a given name. This will abort if the named distribution does + not exist and 'fatalIfMissing' is true. + """ + d = _dists.get(name) + if d is None and fatalIfMissing: + abort('distribution named ' + name + ' not found') + return d + def project(name, fatalIfMissing=True): """ Get the project for a given name. This will abort if the named project does @@ -1001,6 +1051,24 @@ other = JavaCompliance(other) return cmp(self.value, other.value) + +""" +A Java version as defined in JSR-56 +""" +class JavaVersion: + def __init__(self, versionString): + validChar = '[\x21-\x25\x27-\x29\x2c\x2f-\x5e\x60-\x7f]' + separator = '[.-_]' + m = re.match(validChar + '+(' + separator + validChar + '+)*', versionString) + assert m is not None, 'not a recognized version string: ' + versionString + self.versionString = versionString; + self.parts = versionString.split(separator) + + def __str__(self): + return self.versionString + + def __cmp__(self, other): + return cmp(self.parts, other.parts) """ A JavaConfig object encapsulates info on how Java commands are run. @@ -1039,8 +1107,8 @@ output = output.split() assert output[1] == 'version' - self.version = output[2].strip('"') - self.javaCompliance = JavaCompliance(self.version) + self.version = JavaVersion(output[2].strip('"')) + self.javaCompliance = JavaCompliance(self.version.versionString) if self.debug_port is not None: self.java_args += ['-Xdebug', '-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=' + str(self.debug_port)] @@ -1459,6 +1527,9 @@ finally: for n in toBeDeleted: os.remove(n) + + for dist in _dists.values(): + archive(['@' + dist.name]) if suppliedParser: return args @@ -1557,59 +1628,59 @@ return 0 def processorjars(): - projects = set([]) + projects = set() for p in sorted_deps(): - if _needsEclipseJarBuild(p): + if _isAnnotationProcessorDependency(p): projects.add(p) if len(projects) <= 0: return - build(['--projects', ",".join(map(lambda p: p.name, projects))]) - - for p in projects: - targetJar = join(p.dir, p.name + '.jar') - jar(targetJar, [p.output_dir()]) - - -def jar(destFileName, dirs): - latestMod = _latestModification(dirs) - - if exists(destFileName): - mod = os.path.getmtime(destFileName) - if int(round(latestMod*1000)) == int(round(mod*1000)): - # nothing todo - return - - if latestMod is None and exists(destFileName): - return - - jarCmd = [java().jar, 'cf', destFileName] + pnames = [p.name for p in projects] + build(['--projects', ",".join(pnames)]) + archive(pnames) + +def archive(args): + """create jar files for projects and distributions""" + parser = ArgumentParser(prog='mx archive'); + parser.add_argument('names', nargs=REMAINDER, metavar='[<project>|@<distribution>]...') + args = parser.parse_args(args) - for directory in dirs: - jarCmd += ['-C', directory, '.'] - - subprocess.check_call(jarCmd) - log('Written jar file {0}'.format(destFileName)) - - atime = os.path.getatime(destFileName) - os.utime(destFileName, (atime, latestMod)) - -def _latestModification(directories): - latestMod = None - for directory in directories: - if not os.path.exists (directory): - continue - for root, _, files in os.walk(directory): - for names in files: - filepath = os.path.join(root, names) - mod = os.path.getmtime(filepath) - if latestMod is None: - latestMod = mod - elif mod > latestMod: - latestMod = mod - return latestMod + for name in args.names: + if name.startswith('@'): + dname = name[1:] + d = distribution(dname) + fd, tmp = tempfile.mkstemp(suffix='', prefix=basename(d.path) + '.', dir=dirname(d.path)) + zf = zipfile.ZipFile(tmp, 'w') + for p in sorted_deps(d.deps): + outputDir = p.output_dir() + for root, _, files in os.walk(outputDir): + for f in files: + relpath = root[len(outputDir) + 1:] + arcname = join(relpath, f).replace(os.sep, '/') + zf.write(join(root, f), arcname) + zf.close() + os.close(fd) + # Atomic on Unix + shutil.move(tmp, d.path) + #print time.time(), 'move:', tmp, '->', d.path + d.notify_updated() + + else: + p = project(name) + outputDir = p.output_dir() + fd, tmp = tempfile.mkstemp(suffix='', prefix=p.name, dir=p.dir) + zf = zipfile.ZipFile(tmp, 'w') + for root, _, files in os.walk(outputDir): + for f in files: + relpath = root[len(outputDir) + 1:] + arcname = join(relpath, f).replace(os.sep, '/') + zf.write(join(root, f), arcname) + zf.close() + os.close(fd) + # Atomic on Unix + shutil.move(tmp, join(p.dir, p.name + '.jar')) def canonicalizeprojects(args): """process all project files to canonicalize the dependencies @@ -1989,6 +2060,12 @@ if buildProcessorJars: processorjars() + projToDist = dict() + for dist in _dists.values(): + distDeps = sorted_deps(dist.deps) + for p in distDeps: + projToDist[p.name] = (dist, [dep.name for dep in distDeps]) + for p in projects(): if p.native: continue @@ -2103,24 +2180,14 @@ out.element('arguments', data='') out.close('buildCommand') - if (_needsEclipseJarBuild(p)): - targetValues = _genEclipseJarBuild(p); - for value in targetValues: - out.open('buildCommand') - out.element('name', data='org.eclipse.ui.externaltools.ExternalToolBuilder') - out.element('triggers', data='auto,full,incremental,') - out.open('arguments') - out.open('dictionary') - out.element('key', data = 'LaunchConfigHandle') - out.element('value', data = value) - out.close('dictionary') - out.open('dictionary') - out.element('key', data = 'incclean') - out.element('value', data = 'true') - out.close('dictionary') - out.close('arguments') - out.close('buildCommand') - + if _isAnnotationProcessorDependency(p): + _genEclipseBuilder(out, p, 'Jar.launch', 'archive ' + p.name, refresh = False, async = False) + _genEclipseBuilder(out, p, 'Refresh.launch', '', refresh = True, async = True) + + if projToDist.has_key(p.name): + dist, distDeps = projToDist[p.name] + _genEclipseBuilder(out, p, 'Create' + dist.name + 'Dist.launch', 'archive @' + dist.name, refresh=False, async=True) + out.close('buildSpec') out.open('natures') out.element('nature', data='org.eclipse.jdt.core.javanature') @@ -2175,8 +2242,11 @@ make_eclipse_attach('localhost', '8000', deps=projects()) -def _needsEclipseJarBuild(p): - processors = set([]) +def _isAnnotationProcessorDependency(p): + """ + Determines if a given project is part of an annotation processor. + """ + processors = set() for otherProject in projects(): if hasattr(otherProject, 'annotationProcessors') and len(otherProject.annotationProcessors) > 0: @@ -2193,19 +2263,18 @@ return False -def _genEclipseJarBuild(p): - builders = [] - builders.append(_genEclipseLaunch(p, 'Jar.launch', ''.join(['jar ', p.name]), refresh = False, async = False)) - builders.append(_genEclipseLaunch(p, 'Refresh.launch', '', refresh = True, async = True)) - return builders - -def _genEclipseLaunch(p, name, mxCommand, refresh=True, async=False): +def _genEclipseBuilder(dotProjectDoc, p, name, mxCommand, refresh=True, async=False, logToConsole=False): launchOut = XMLDoc(); + consoleOn = 'true' if logToConsole else 'false' launchOut.open('launchConfiguration', {'type' : 'org.eclipse.ui.externaltools.ProgramBuilderLaunchConfigurationType'}) + launchOut.open('mapAttribute', {'key' : 'org.eclipse.debug.core.environmentVariables'}) + launchOut.element('mapEntry', {'key' : 'JAVA_HOME', 'value' : java().jdk}) + launchOut.close('mapAttribute') + if refresh: launchOut.element('stringAttribute', {'key' : 'org.eclipse.debug.core.ATTR_REFRESH_SCOPE', 'value': '${project}'}) - launchOut.element('booleanAttribute', {'key' : 'org.eclipse.debug.core.capture_output', 'value': 'false'}) - launchOut.element('booleanAttribute', {'key' : 'org.eclipse.debug.ui.ATTR_CONSOLE_OUTPUT_ON', 'value': 'false'}) + launchOut.element('booleanAttribute', {'key' : 'org.eclipse.debug.ui.ATTR_CONSOLE_OUTPUT_ON', 'value': consoleOn}) + launchOut.element('booleanAttribute', {'key' : 'org.eclipse.debug.core.capture_output', 'value': consoleOn}) if async: launchOut.element('booleanAttribute', {'key' : 'org.eclipse.debug.ui.ATTR_LAUNCH_IN_BACKGROUND', 'value': 'true'}) @@ -2229,9 +2298,21 @@ os.makedirs(externalToolDir) update_file(join(externalToolDir, name), launchOut.xml(indent='\t', newl='\n')) - return ''.join(["<project>/.externalToolBuilders/", name]) - - + dotProjectDoc.open('buildCommand') + dotProjectDoc.element('name', data='org.eclipse.ui.externaltools.ExternalToolBuilder') + dotProjectDoc.element('triggers', data='auto,full,incremental,') + dotProjectDoc.open('arguments') + dotProjectDoc.open('dictionary') + dotProjectDoc.element('key', data = 'LaunchConfigHandle') + dotProjectDoc.element('value', data = '<project>/.externalToolBuilders/' + name) + dotProjectDoc.close('dictionary') + dotProjectDoc.open('dictionary') + dotProjectDoc.element('key', data = 'incclean') + dotProjectDoc.element('value', data = 'true') + dotProjectDoc.close('dictionary') + dotProjectDoc.close('arguments') + dotProjectDoc.close('buildCommand') + def netbeansinit(args, suite=None): """(re)generate NetBeans project configurations""" @@ -2256,6 +2337,14 @@ out.open('project', {'name' : p.name, 'default' : 'default', 'basedir' : '.'}) out.element('description', data='Builds, tests, and runs the project ' + p.name + '.') out.element('import', {'file' : 'nbproject/build-impl.xml'}) + out.open('target', {'name' : '-post-compile'}) + out.open('exec', { 'executable' : sys.executable}) + out.element('env', {'key' : 'JAVA_HOME', 'value' : java().jdk}) + out.element('arg', {'value' : os.path.abspath(__file__)}) + out.element('arg', {'value' : 'archive'}) + out.element('arg', {'value' : '@GRAAL'}) + out.close('exec') + out.close('target') out.close('project') updated = update_file(join(p.dir, 'build.xml'), out.xml(indent='\t', newl='\n')) or updated @@ -2303,7 +2392,7 @@ updated = update_file(join(p.dir, 'nbproject', 'project.xml'), out.xml(indent=' ', newl='\n')) or updated out = StringIO.StringIO() - jdkPlatform = 'JDK_' + java().version + jdkPlatform = 'JDK_' + str(java().version) annotationProcessorEnabled = "false" annotationProcessorReferences = "" @@ -2444,7 +2533,7 @@ if updated: log('If using NetBeans:') - log(' 1. Ensure that a platform named "JDK ' + java().version + '" is defined (Tools -> Java Platforms)') + log(' 1. Ensure that a platform named "JDK_' + str(java().version) + '" is defined (Tools -> Java Platforms)') log(' 2. Open/create a Project Group for the directory containing the projects (File -> Project Group -> New Group... -> Folder of Projects)') def ideclean(args, suite=None): @@ -2474,6 +2563,24 @@ """(re)generate Eclipse and NetBeans project configurations""" eclipseinit(args, suite) netbeansinit(args, suite) + fsckprojects([]) + +def fsckprojects(args): + """find directories corresponding to deleted Java projects and delete them""" + for suite in suites(): + projectDirs = [p.dir for p in suite.projects] + for root, dirnames, files in os.walk(suite.dir): + currentDir = join(suite.dir, root) + if currentDir in projectDirs: + # don't traverse subdirs of an existing project + dirnames[:] = [] + else: + projectConfigFiles = frozenset(['.classpath', 'nbproject']) + indicators = projectConfigFiles.intersection(files) + if len(indicators) != 0: + if not sys.stdout.isatty() or raw_input(currentDir + ' looks like a removed project -- delete it? [yn]: ') == 'y': + shutil.rmtree(currentDir) + log('Deleted ' + currentDir) def javadoc(args, parser=None, docDir='javadoc', includeDeps=True): """generate javadoc for some/all Java projects""" @@ -2926,9 +3033,11 @@ 'eclipseinit': [eclipseinit, ''], 'eclipseformat': [eclipseformat, ''], 'findclass': [findclass, ''], + 'fsckprojects': [fsckprojects, ''], 'help': [help_, '[command]'], 'ideclean': [ideclean, ''], 'ideinit': [ideinit, ''], + 'archive': [archive, '[options]'], 'projectgraph': [projectgraph, ''], 'javap': [javap, ''], 'javadoc': [javadoc, '[options]'],
--- a/src/cpu/sparc/vm/c1_CodeStubs_sparc.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/cpu/sparc/vm/c1_CodeStubs_sparc.cpp Tue Mar 12 11:38:52 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 __
--- a/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp Tue Mar 12 11:38:52 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);
--- a/src/cpu/sparc/vm/c2_globals_sparc.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/cpu/sparc/vm/c2_globals_sparc.hpp Tue Mar 12 11:38:52 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);
--- a/src/cpu/sparc/vm/cppInterpreter_sparc.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/cpu/sparc/vm/cppInterpreter_sparc.cpp Tue Mar 12 11:38:52 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
--- a/src/cpu/sparc/vm/frame_sparc.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/cpu/sparc/vm/frame_sparc.cpp Tue Mar 12 11:38:52 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.
--- a/src/cpu/sparc/vm/frame_sparc.inline.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/cpu/sparc/vm/frame_sparc.inline.hpp Tue Mar 12 11:38:52 2013 +0100 @@ -74,8 +74,7 @@ // return address: -inline address* frame::sender_pc_addr() const { return (address*) (I7_addr() + pc_return_offset); } -inline address frame::sender_pc() const { return *sender_pc_addr(); } +inline address frame::sender_pc() const { return *I7_addr() + pc_return_offset; } inline address* frame::I7_addr() const { return (address*) &sp()[ I7->sp_offset_in_saved_window()]; } inline address* frame::I0_addr() const { return (address*) &sp()[ I0->sp_offset_in_saved_window()]; }
--- a/src/cpu/sparc/vm/jniTypes_sparc.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/cpu/sparc/vm/jniTypes_sparc.hpp Tue Mar 12 11:38:52 2013 +0100 @@ -112,25 +112,6 @@ return *(jdouble *)&jl; } #endif - static inline jint get_int (intptr_t *from, int& pos) { - return get_int(from + pos++); - } - static inline jlong get_long (intptr_t *from, int& pos) { - jlong result = get_long(from + pos); - pos += 2; - return result; - } - static inline oop get_obj (intptr_t *from, int& pos) { - return get_obj(from + pos++); - } - static inline jfloat get_float (intptr_t *from, int& pos) { - return get_float(from + pos++); - } - static inline jdouble get_double(intptr_t *from, int& pos) { - jdouble result = get_double(from + pos); - pos += 2; - return result; - } }; #endif // CPU_SPARC_VM_JNITYPES_SPARC_HPP
--- a/src/cpu/sparc/vm/macroAssembler_sparc.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/cpu/sparc/vm/macroAssembler_sparc.cpp Tue Mar 12 11:38:52 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) {
--- a/src/cpu/sparc/vm/macroAssembler_sparc.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/cpu/sparc/vm/macroAssembler_sparc.hpp Tue Mar 12 11:38:52 2013 +0100 @@ -26,6 +26,7 @@ #define CPU_SPARC_VM_MACROASSEMBLER_SPARC_HPP #include "asm/assembler.hpp" +#include "utilities/macros.hpp" // <sys/trap.h> 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();
--- a/src/cpu/sparc/vm/templateInterpreter_sparc.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/cpu/sparc/vm/templateInterpreter_sparc.cpp Tue Mar 12 11:38:52 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
--- a/src/cpu/sparc/vm/templateTable_sparc.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/cpu/sparc/vm/templateTable_sparc.cpp Tue Mar 12 11:38:52 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);
--- a/src/cpu/x86/vm/assembler_x86.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/cpu/x86/vm/assembler_x86.cpp Tue Mar 12 11:38:52 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) {
--- a/src/cpu/x86/vm/assembler_x86.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/cpu/x86/vm/assembler_x86.hpp Tue Mar 12 11:38:52 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
--- a/src/cpu/x86/vm/c1_CodeStubs_x86.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/cpu/x86/vm/c1_CodeStubs_x86.cpp Tue Mar 12 11:38:52 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 __
--- a/src/cpu/x86/vm/c1_Runtime1_x86.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/cpu/x86/vm/c1_Runtime1_x86.cpp Tue Mar 12 11:38:52 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);
--- a/src/cpu/x86/vm/c2_globals_x86.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/cpu/x86/vm/c2_globals_x86.hpp Tue Mar 12 11:38:52 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);
--- a/src/cpu/x86/vm/cppInterpreter_x86.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/cpu/x86/vm/cppInterpreter_x86.cpp Tue Mar 12 11:38:52 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
--- a/src/cpu/x86/vm/frame_x86.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/cpu/x86/vm/frame_x86.cpp Tue Mar 12 11:38:52 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. @@ -302,11 +308,6 @@ ptr_at_put(interpreter_frame_sender_sp_offset, (intptr_t) sender_sp); } -intptr_t** frame::interpreter_frame_sender_sp_addr() const { - assert(is_interpreted_frame(), "interpreted frame expected"); - return (intptr_t**) addr_at(interpreter_frame_sender_sp_offset); -} - // monitor elements
--- a/src/cpu/x86/vm/frame_x86.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/cpu/x86/vm/frame_x86.hpp Tue Mar 12 11:38:52 2013 +0100 @@ -191,12 +191,13 @@ // Note: not necessarily the real 'frame pointer' (see real_fp) intptr_t* fp() const { return _fp; } + inline address* sender_pc_addr() const; + // return address of param, zero origin index. inline address* native_param_addr(int idx) const; // expression stack tos if we are nested in a java call intptr_t* interpreter_frame_last_sp() const; - intptr_t** interpreter_frame_last_sp_addr() const; // helper to update a map with callee-saved RBP static void update_map_with_saved_link(RegisterMap* map, intptr_t** link_addr);
--- a/src/cpu/x86/vm/frame_x86.inline.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/cpu/x86/vm/frame_x86.inline.hpp Tue Mar 12 11:38:52 2013 +0100 @@ -133,9 +133,8 @@ -inline intptr_t* frame::link() const { return (intptr_t*) *(intptr_t **)addr_at(link_offset); } -inline intptr_t** frame::link_addr() const { return (intptr_t **)addr_at(link_offset); } -inline void frame::set_link(intptr_t* addr) { *(intptr_t **)addr_at(link_offset) = addr; } +inline intptr_t* frame::link() const { return (intptr_t*) *(intptr_t **)addr_at(link_offset); } +inline void frame::set_link(intptr_t* addr) { *(intptr_t **)addr_at(link_offset) = addr; } inline intptr_t* frame::unextended_sp() const { return _unextended_sp; } @@ -211,10 +210,6 @@ return *(intptr_t**)addr_at(interpreter_frame_last_sp_offset); } -inline intptr_t** frame::interpreter_frame_last_sp_addr() const { - return (intptr_t**)addr_at(interpreter_frame_last_sp_offset); -} - inline intptr_t* frame::interpreter_frame_bcx_addr() const { return (intptr_t*)addr_at(interpreter_frame_bcx_offset); }
--- a/src/cpu/x86/vm/graalRuntime_x86.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/cpu/x86/vm/graalRuntime_x86.cpp Tue Mar 12 11:38:52 2013 +0100 @@ -46,12 +46,6 @@ assert(!(oop_result1->is_valid() || metadata_result->is_valid()) || oop_result1 != metadata_result, "registers must be different"); assert(oop_result1 != thread && metadata_result != thread, "registers must be different"); assert(args_size >= 0, "illegal args_size"); - bool align_stack = false; -#ifdef _LP64 - // At a method handle call, the stack may not be properly aligned - // when returning with an exception. - align_stack = (stub_id() == false /*GraalRuntime::handle_exception_from_callee_id*/); -#endif #ifdef _LP64 mov(c_rarg0, thread); @@ -65,20 +59,11 @@ #endif // _LP64 int call_offset; - if (!align_stack) { - set_last_Java_frame(thread, noreg, rbp, NULL); - } else { - address the_pc = pc(); - call_offset = offset(); - set_last_Java_frame(thread, noreg, rbp, the_pc); - andptr(rsp, -(StackAlignmentInBytes)); // Align stack - } + set_last_Java_frame(thread, rsp, noreg, NULL); // do the call call(RuntimeAddress(entry)); - if (!align_stack) { - call_offset = offset(); - } + call_offset = offset(); // verify callee-saved register #ifdef ASSERT guarantee(thread != rax, "change this code"); @@ -93,7 +78,7 @@ } pop(rax); #endif - reset_last_Java_frame(thread, true, align_stack); + reset_last_Java_frame(thread, true, false); // discard thread and arguments NOT_LP64(addptr(rsp, num_rt_args()*BytesPerWord)); @@ -356,6 +341,7 @@ map->set_callee_saved(VMRegImpl::stack2reg(rcx_off + num_rt_args), rcx->as_VMReg()); map->set_callee_saved(VMRegImpl::stack2reg(rdx_off + num_rt_args), rdx->as_VMReg()); map->set_callee_saved(VMRegImpl::stack2reg(rbx_off + num_rt_args), rbx->as_VMReg()); + map->set_callee_saved(VMRegImpl::stack2reg(rbp_off + num_rt_args), rbp->as_VMReg()); map->set_callee_saved(VMRegImpl::stack2reg(rsi_off + num_rt_args), rsi->as_VMReg()); map->set_callee_saved(VMRegImpl::stack2reg(rdi_off + num_rt_args), rdi->as_VMReg()); #ifdef _LP64 @@ -373,6 +359,7 @@ map->set_callee_saved(VMRegImpl::stack2reg(rcxH_off + num_rt_args), rcx->as_VMReg()->next()); map->set_callee_saved(VMRegImpl::stack2reg(rdxH_off + num_rt_args), rdx->as_VMReg()->next()); map->set_callee_saved(VMRegImpl::stack2reg(rbxH_off + num_rt_args), rbx->as_VMReg()->next()); + map->set_callee_saved(VMRegImpl::stack2reg(rbpH_off + num_rt_args), rbp->as_VMReg()->next()); map->set_callee_saved(VMRegImpl::stack2reg(rsiH_off + num_rt_args), rsi->as_VMReg()->next()); map->set_callee_saved(VMRegImpl::stack2reg(rdiH_off + num_rt_args), rdi->as_VMReg()->next()); @@ -638,9 +625,9 @@ OopMapSet* oop_maps = new OopMapSet(); OopMap* oop_map = NULL; switch (id) { - case graal_handle_exception_nofpu_id: + case handle_exception_nofpu_id: // At this point all registers MAY be live. - oop_map = save_live_registers(sasm, 1 /*thread*/, id == graal_handle_exception_nofpu_id); + oop_map = save_live_registers(sasm, 1 /*thread*/, id == handle_exception_nofpu_id); break; default: ShouldNotReachHere(); } @@ -712,9 +699,9 @@ __ movptr(Address(rbp, 1*BytesPerWord), rax); switch (id) { - case graal_handle_exception_nofpu_id: + case handle_exception_nofpu_id: // Restore the registers that were saved at the beginning. - restore_live_registers(sasm, id == graal_handle_exception_nofpu_id); + restore_live_registers(sasm, id == handle_exception_nofpu_id); break; default: ShouldNotReachHere(); } @@ -824,7 +811,7 @@ OopMapSet* oop_maps = NULL; switch (id) { - case graal_new_instance_id: + case new_instance_id: { Register klass = rdx; // Incoming Register obj = rax; // Result @@ -844,7 +831,7 @@ break; - case graal_new_array_id: + case new_array_id: { Register length = rbx; // Incoming Register klass = rdx; // Incoming @@ -869,7 +856,7 @@ } break; - case graal_new_multi_array_id: + case new_multi_array_id: { GraalStubFrame f(sasm, "new_multi_array", dont_gc_arguments); // rax,: klass // rbx,: rank @@ -886,7 +873,7 @@ } break; - case graal_register_finalizer_id: + case register_finalizer_id: { __ set_info("register_finalizer", dont_gc_arguments); @@ -927,75 +914,16 @@ } break; - case graal_handle_exception_nofpu_id: + case handle_exception_nofpu_id: { GraalStubFrame f(sasm, "handle_exception", dont_gc_arguments); oop_maps = generate_handle_exception(id, sasm); } break; - case graal_slow_subtype_check_id: - { - // Typical calling sequence: - // __ push(klass_RInfo); // object klass or other subclass - // __ push(sup_k_RInfo); // array element klass or other superclass - // __ call(slow_subtype_check); - // Note that the subclass is pushed first, and is therefore deepest. - // Previous versions of this code reversed the names 'sub' and 'super'. - // This was operationally harmless but made the code unreadable. - enum layout { - rax_off, SLOT2(raxH_off) - rcx_off, SLOT2(rcxH_off) - rsi_off, SLOT2(rsiH_off) - rdi_off, SLOT2(rdiH_off) - // saved_rbp_off, SLOT2(saved_rbpH_off) - return_off, SLOT2(returnH_off) - sup_k_off, SLOT2(sup_kH_off) - klass_off, SLOT2(superH_off) - framesize, - result_off = klass_off // deepest argument is also the return value - }; - - __ set_info("slow_subtype_check", dont_gc_arguments); - __ push(rdi); - __ push(rsi); - __ push(rcx); - __ push(rax); - - // This is called by pushing args and not with C abi - __ movptr(rsi, Address(rsp, (klass_off) * VMRegImpl::stack_slot_size)); // subclass - __ movptr(rax, Address(rsp, (sup_k_off) * VMRegImpl::stack_slot_size)); // superclass - - Label miss; - Label success; - __ check_klass_subtype_fast_path(rsi, rax, rcx, &success, &miss, NULL); - - __ check_klass_subtype_slow_path(rsi, rax, rcx, rdi, NULL, &miss); - - // fallthrough on success: - __ bind(success); - __ movptr(Address(rsp, (result_off) * VMRegImpl::stack_slot_size), 1); // result - __ pop(rax); - __ pop(rcx); - __ pop(rsi); - __ pop(rdi); - __ ret(0); - - __ bind(miss); - __ movptr(Address(rsp, (result_off) * VMRegImpl::stack_slot_size), NULL_WORD); // result - __ pop(rax); - __ pop(rcx); - __ pop(rsi); - __ pop(rdi); - __ ret(0); - } - break; - - case graal_unwind_exception_call_id: { + case unwind_exception_call_id: { // remove the frame from the stack __ movptr(rsp, rbp); __ pop(rbp); - // exception_oop is passed using ordinary java calling conventions - __ movptr(rax, j_rarg0); Label nonNullExceptionOop; __ testptr(rax, rax); @@ -1004,7 +932,7 @@ __ enter(); oop_maps = new OopMapSet(); OopMap* oop_map = save_live_registers(sasm, 0); - int call_offset = __ call_RT(rax, noreg, (address)graal_create_null_exception, 0); + int call_offset = __ call_RT(rax, noreg, (address)create_null_exception, 0); oop_maps->add_gc_map(call_offset, oop_map); __ leave(); } @@ -1018,7 +946,7 @@ break; } - case graal_OSR_migration_end_id: { + case OSR_migration_end_id: { __ enter(); save_live_registers(sasm, 0); __ movptr(c_rarg0, j_rarg0); @@ -1029,39 +957,33 @@ break; } - case graal_set_deopt_info_id: { - __ movptr(Address(r15_thread, JavaThread::graal_deopt_info_offset()), rscratch1); - __ ret(0); - break; - } - - case graal_create_null_pointer_exception_id: { + case create_null_pointer_exception_id: { __ enter(); oop_maps = new OopMapSet(); OopMap* oop_map = save_live_registers(sasm, 0); - int call_offset = __ call_RT(rax, noreg, (address)graal_create_null_exception, 0); + int call_offset = __ call_RT(rax, noreg, (address)create_null_exception, 0); oop_maps->add_gc_map(call_offset, oop_map); __ leave(); __ ret(0); break; } - case graal_create_out_of_bounds_exception_id: { + case create_out_of_bounds_exception_id: { __ enter(); oop_maps = new OopMapSet(); OopMap* oop_map = save_live_registers(sasm, 0); - int call_offset = __ call_RT(rax, noreg, (address)graal_create_out_of_bounds_exception, j_rarg0); + int call_offset = __ call_RT(rax, noreg, (address)create_out_of_bounds_exception, j_rarg0); oop_maps->add_gc_map(call_offset, oop_map); __ leave(); __ ret(0); break; } - case graal_vm_error_id: { + case vm_error_id: { __ enter(); oop_maps = new OopMapSet(); OopMap* oop_map = save_live_registers(sasm, 0); - int call_offset = __ call_RT(noreg, noreg, (address)graal_vm_error, j_rarg0, j_rarg1, j_rarg2); + int call_offset = __ call_RT(noreg, noreg, (address)vm_error, j_rarg0, j_rarg1, j_rarg2); oop_maps->add_gc_map(call_offset, oop_map); restore_live_registers(sasm); __ leave(); @@ -1069,11 +991,11 @@ break; } - case graal_log_printf_id: { + case log_printf_id: { __ enter(); oop_maps = new OopMapSet(); OopMap* oop_map = save_live_registers(sasm, 0); - int call_offset = __ call_RT(noreg, noreg, (address)graal_log_printf, j_rarg0, j_rarg1, j_rarg2, j_rarg3); + int call_offset = __ call_RT(noreg, noreg, (address)log_printf, j_rarg0, j_rarg1, j_rarg2, j_rarg3); oop_maps->add_gc_map(call_offset, oop_map); restore_live_registers(sasm); __ leave(); @@ -1081,11 +1003,11 @@ break; } - case graal_log_primitive_id: { + case log_primitive_id: { __ enter(); oop_maps = new OopMapSet(); OopMap* oop_map = save_live_registers(sasm, 0); - int call_offset = __ call_RT(noreg, noreg, (address)graal_log_primitive, j_rarg0, j_rarg1, j_rarg2); + int call_offset = __ call_RT(noreg, noreg, (address)log_primitive, j_rarg0, j_rarg1, j_rarg2); oop_maps->add_gc_map(call_offset, oop_map); restore_live_registers(sasm); __ leave(); @@ -1093,11 +1015,11 @@ break; } - case graal_log_object_id: { + case log_object_id: { __ enter(); oop_maps = new OopMapSet(); OopMap* oop_map = save_live_registers(sasm, 0); - int call_offset = __ call_RT(noreg, noreg, (address)graal_log_object, j_rarg0, j_rarg1); + int call_offset = __ call_RT(noreg, noreg, (address)log_object, j_rarg0, j_rarg1); oop_maps->add_gc_map(call_offset, oop_map); restore_live_registers(sasm); __ leave(); @@ -1105,7 +1027,7 @@ break; } - case graal_verify_oop_id: { + case verify_oop_id: { // We use enter & leave so that a better stack trace is produced in the hs_err file __ enter(); __ verify_oop(r13, "Graal verify oop"); @@ -1114,7 +1036,7 @@ break; } - case graal_arithmetic_frem_id: { + case arithmetic_frem_id: { __ subptr(rsp, 8); __ movflt(Address(rsp, 0), xmm1); __ fld_s(Address(rsp, 0)); @@ -1135,7 +1057,7 @@ __ ret(0); break; } - case graal_arithmetic_drem_id: { + case arithmetic_drem_id: { __ subptr(rsp, 8); __ movdbl(Address(rsp, 0), xmm1); __ fld_d(Address(rsp, 0)); @@ -1156,15 +1078,15 @@ __ ret(0); break; } - case graal_monitorenter_id: { + case monitorenter_id: { Register obj = j_rarg0; Register lock = j_rarg1; { - GraalStubFrame f(sasm, "graal_monitorenter", dont_gc_arguments); + GraalStubFrame f(sasm, "monitorenter", dont_gc_arguments); OopMap* map = save_live_registers(sasm, 2, save_fpu_registers); // Called with store_parameter and not C abi - int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, graal_monitorenter), obj, lock); + int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, monitorenter), obj, lock); oop_maps = new OopMapSet(); oop_maps->add_gc_map(call_offset, map); @@ -1173,17 +1095,17 @@ __ ret(0); break; } - case graal_monitorexit_id: { + case monitorexit_id: { Register obj = j_rarg0; Register lock = j_rarg1; { - GraalStubFrame f(sasm, "graal_monitorexit", dont_gc_arguments); + GraalStubFrame f(sasm, "monitorexit", dont_gc_arguments); OopMap* map = save_live_registers(sasm, 2, save_fpu_registers); // note: really a leaf routine but must setup last java sp // => use call_RT for now (speed can be improved by // doing last java sp setup manually) - int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, graal_monitorexit), obj, lock); + int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, monitorexit), obj, lock); oop_maps = new OopMapSet(); oop_maps->add_gc_map(call_offset, map); @@ -1193,12 +1115,12 @@ break; } - case graal_identity_hash_code_id: { + case identity_hash_code_id: { Register obj = j_rarg0; // Incoming __ set_info("identity_hash_code", dont_gc_arguments); __ enter(); OopMap* map = save_live_registers(sasm, 1); - int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, graal_identity_hash_code), obj); + int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, identity_hash_code), obj); oop_maps = new OopMapSet(); oop_maps->add_gc_map(call_offset, map); restore_live_registers_except_rax(sasm); @@ -1206,14 +1128,14 @@ __ ret(0); break; } - case graal_thread_is_interrupted_id: { + case thread_is_interrupted_id: { Register thread = j_rarg0; Register clear_interrupted = j_rarg1; __ set_info("identity_hash_code", dont_gc_arguments); __ enter(); OopMap* map = save_live_registers(sasm, 1); - int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, graal_thread_is_interrupted), thread, clear_interrupted); + int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, thread_is_interrupted), thread, clear_interrupted); oop_maps = new OopMapSet(); oop_maps->add_gc_map(call_offset, map); restore_live_registers_except_rax(sasm);
--- a/src/cpu/x86/vm/jniTypes_x86.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/cpu/x86/vm/jniTypes_x86.hpp Tue Mar 12 11:38:52 2013 +0100 @@ -127,26 +127,6 @@ static inline oop get_obj (intptr_t *from) { return *(oop *) from; } static inline jfloat get_float (intptr_t *from) { return *(jfloat *) from; } static inline jdouble get_double(intptr_t *from) { return *(jdouble *)(from + _JNI_SLOT_OFFSET); } - - static inline jint get_int (intptr_t *from, int& pos) { - return get_int(from + pos++); - } - static inline jlong get_long (intptr_t *from, int& pos) { - jlong result = get_long(from + pos); - pos += 2; - return result; - } - static inline oop get_obj (intptr_t *from, int& pos) { - return get_obj(from + pos++); - } - static inline jfloat get_float (intptr_t *from, int& pos) { - return get_float(from + pos++); - } - static inline jdouble get_double(intptr_t *from, int& pos) { - jdouble result = get_double(from + pos); - pos += 2; - return result; - } #undef _JNI_SLOT_OFFSET };
--- a/src/cpu/x86/vm/macroAssembler_x86.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/cpu/x86/vm/macroAssembler_x86.cpp Tue Mar 12 11:38:52 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;
--- a/src/cpu/x86/vm/macroAssembler_x86.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/cpu/x86/vm/macroAssembler_x86.hpp Tue Mar 12 11:38:52 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);
--- a/src/cpu/x86/vm/nativeInst_x86.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/cpu/x86/vm/nativeInst_x86.hpp Tue Mar 12 11:38:52 2013 +0100 @@ -574,15 +574,18 @@ return false; } } else { - if (ubyte_at(0) == Assembler::REX_WR && ubyte_at(1) == NativeMovRegMem::instruction_code_mem2reg && ubyte_at(2) == 0x15) { // mov r10, rip[...] - address fault = addr_at(7) + int_at(3); - return os::is_poll_address(fault); - } else if (ubyte_at(0) == NativeTstRegMem::instruction_code_memXregl && ubyte_at(1) == 0x05) { // 00 rax 101 +#ifdef GRAAL + // Graal may allocate an arbitrary register for storing the polling address. + return true; +#else + if (ubyte_at(0) == NativeTstRegMem::instruction_code_memXregl && + ubyte_at(1) == 0x05) { // 00 rax 101 address fault = addr_at(6) + int_at(2); return os::is_poll_address(fault); } else { return false; } +#endif } #else return ( ubyte_at(0) == NativeMovRegMem::instruction_code_mem2reg ||
--- a/src/cpu/x86/vm/sharedRuntime_x86_32.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/cpu/x86/vm/sharedRuntime_x86_32.cpp Tue Mar 12 11:38:52 2013 +0100 @@ -1763,8 +1763,7 @@ int vep_offset = ((intptr_t)__ pc()) - start; -#if defined(COMPILER1) || defined(GRAAL) - +#ifdef COMPILER1 if (InlineObjectHash && method->intrinsic_id() == vmIntrinsics::_hashCode) { // Object.hashCode can pull the hashCode from the header word // instead of doing a full VM transition once it's been computed. @@ -1793,7 +1792,7 @@ __ ret(0); __ bind (slowCase); } -#endif // COMPILER1 || GRAAL +#endif // COMPILER1 // The instruction at the verified entry point must be 5 bytes or longer // because it can be patched on the fly by make_non_entrant. The stack bang
--- a/src/cpu/x86/vm/sharedRuntime_x86_64.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/cpu/x86/vm/sharedRuntime_x86_64.cpp Tue Mar 12 11:38:52 2013 +0100 @@ -1996,50 +1996,6 @@ int vep_offset = ((intptr_t)__ pc()) - start; -#ifdef GRAALVM - if (InlineObjectHash && (method->intrinsic_id() == vmIntrinsics::_hashCode || method->intrinsic_id() == vmIntrinsics::_identityHashCode)) { - // Object.hashCode can pull the hashCode from the header word - // instead of doing a full VM transition once it's been computed. - // Since hashCode is usually polymorphic at call sites we can't do - // this optimization at the call site without a lot of work. - Label slowCase; - Label nullCase; - Register result = rax; - - if (method->intrinsic_id() == vmIntrinsics::_identityHashCode) { - __ cmpptr(receiver, 0); - __ jcc(Assembler::equal, nullCase); - } - - __ movptr(result, Address(receiver, oopDesc::mark_offset_in_bytes())); - - // check if locked - __ testptr(result, markOopDesc::unlocked_value); - __ jcc (Assembler::zero, slowCase); - - if (UseBiasedLocking) { - // Check if biased and fall through to runtime if so - __ testptr(result, markOopDesc::biased_lock_bit_in_place); - __ jcc (Assembler::notZero, slowCase); - } - - // get hash - __ shrptr(result, markOopDesc::hash_shift); - __ andptr(result, markOopDesc::hash_mask); - // test if hashCode exists - __ jcc (Assembler::zero, slowCase); - __ ret(0); - - if (method->intrinsic_id() == vmIntrinsics::_identityHashCode) { - __ bind(nullCase); - __ movl(result, 0); - __ ret(0); - } - - __ bind (slowCase); - } -#endif // GRAALVM - // The instruction at the verified entry point must be 5 bytes or longer // because it can be patched on the fly by make_non_entrant. The stack bang // instruction fits that requirement.
--- a/src/cpu/x86/vm/templateInterpreter_x86_32.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/cpu/x86/vm/templateInterpreter_x86_32.cpp Tue Mar 12 11:38:52 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
--- a/src/cpu/x86/vm/templateInterpreter_x86_64.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/cpu/x86/vm/templateInterpreter_x86_64.cpp Tue Mar 12 11:38:52 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
--- a/src/cpu/x86/vm/templateTable_x86_32.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/cpu/x86/vm/templateTable_x86_32.cpp Tue Mar 12 11:38:52 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: {
--- a/src/cpu/x86/vm/templateTable_x86_64.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/cpu/x86/vm/templateTable_x86_64.cpp Tue Mar 12 11:38:52 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: {
--- a/src/cpu/zero/vm/assembler_zero.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/cpu/zero/vm/assembler_zero.cpp Tue Mar 12 11:38:52 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;
--- a/src/cpu/zero/vm/cppInterpreter_zero.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/cpu/zero/vm/cppInterpreter_zero.cpp Tue Mar 12 11:38:52 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
--- a/src/cpu/zero/vm/shark_globals_zero.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/cpu/zero/vm/shark_globals_zero.hpp Tue Mar 12 11:38:52 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 );
--- a/src/os/bsd/vm/osThread_bsd.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/os/bsd/vm/osThread_bsd.hpp Tue Mar 12 11:38:52 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. // ***************************************************************
--- a/src/os/bsd/vm/os_bsd.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/os/bsd/vm/os_bsd.cpp Tue Mar 12 11:38:52 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; } @@ -3619,9 +3635,9 @@ // able to use structured exception handling (thread-local exception filters) // on, e.g., Win32. void -os::os_exception_wrapper(java_call_t f, JavaValue* value, methodHandle* method, nmethod* nm, +os::os_exception_wrapper(java_call_t f, JavaValue* value, methodHandle* method, JavaCallArguments* args, Thread* thread) { - f(value, method, nm, args, thread); + f(value, method, args, thread); } void os::print_statistics() {
--- a/src/os/linux/vm/os_linux.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/os/linux/vm/os_linux.cpp Tue Mar 12 11:38:52 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; } } @@ -4447,9 +4434,9 @@ // able to use structured exception handling (thread-local exception filters) // on, e.g., Win32. void -os::os_exception_wrapper(java_call_t f, JavaValue* value, methodHandle* method, nmethod* nm, +os::os_exception_wrapper(java_call_t f, JavaValue* value, methodHandle* method, JavaCallArguments* args, Thread* thread) { - f(value, method, nm, args, thread); + f(value, method, args, thread); } void os::print_statistics() { @@ -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/<pid>/cpu since this is faster to - // process. If this file is not present (linux kernels 2.5 and above) - // then we open /proc/<pid>/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/<tid>/stat aggregates per-process usage on // new Linux kernels 2.6+ where NPTL is supported. // The /proc/self/task/<tid>/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
--- a/src/os/solaris/vm/os_solaris.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/os/solaris/vm/os_solaris.cpp Tue Mar 12 11:38:52 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 @@ -4280,8 +4280,8 @@ // This does not do anything on Solaris. This is basically a hook for being // able to use structured exception handling (thread-local exception filters) on, e.g., Win32. -void os::os_exception_wrapper(java_call_t f, JavaValue* value, methodHandle* method, nmethod* nm, JavaCallArguments* args, Thread* thread) { - f(value, method, nm, args, thread); +void os::os_exception_wrapper(java_call_t f, JavaValue* value, methodHandle* method, JavaCallArguments* args, Thread* thread) { + f(value, method, args, thread); } // This routine may be used by user applications as a "hook" to catch signals. @@ -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)
--- a/src/os/windows/vm/os_windows.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/os/windows/vm/os_windows.cpp Tue Mar 12 11:38:52 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) {
--- a/src/os_cpu/bsd_x86/vm/globals_bsd_x86.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/os_cpu/bsd_x86/vm/globals_bsd_x86.hpp Tue Mar 12 11:38:52 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);
--- a/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp Tue Mar 12 11:38:52 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); }
--- a/src/os_cpu/bsd_x86/vm/vmStructs_bsd_x86.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/os_cpu/bsd_x86/vm/vmStructs_bsd_x86.hpp Tue Mar 12 11:38:52 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)
--- a/src/os_cpu/linux_x86/vm/os_linux_x86.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/os_cpu/linux_x86/vm/os_linux_x86.cpp Tue Mar 12 11:38:52 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); } @@ -282,17 +282,6 @@ } #endif // AMD64 - if (TraceSignals) { - CodeBlob* cb = CodeCache::find_blob(pc); - if (cb != NULL && cb->is_nmethod()) { - nmethod* nm = (nmethod*)cb; - int rel = pc - nm->code_begin(); - tty->print_cr(err_msg("Implicit exception at %d of method %s", rel, nm->method()->name()->as_C_string())); - } else { - tty->print_cr("No code blob found for %x", pc); - } - } - // Handle ALL stack overflow variations here if (sig == SIGSEGV) { address addr = (address) info->si_addr; @@ -306,7 +295,6 @@ if (thread->thread_state() == _thread_in_Java) { // Throw a stack overflow exception. Guard pages will be reenabled // while unwinding the stack. - if (WizardMode) tty->print("implicit: %08x%08x\n", ((long long)pc) >> 32, pc); stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::STACK_OVERFLOW); } else { // Thread was in the vm or native code. Return and try to finish. @@ -392,15 +380,8 @@ #endif // AMD64 } else if (sig == SIGSEGV && !MacroAssembler::needs_explicit_null_check((intptr_t)info->si_addr)) { - if (TraceSignals) { - tty->print_cr("Implicit exception continuation"); - } // Determination of interpreter/vtable stub/compiled code null exception stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::IMPLICIT_NULL); - } else if (sig == SIGSEGV) { - if (TraceSignals) { - tty->print_cr("would have needed explicit null check %d", (intptr_t)info->si_addr); - } } } else if (thread->thread_state() == _thread_in_vm && sig == SIGBUS && /* info->si_code == BUS_OBJERR && */
--- a/src/os_cpu/windows_x86/vm/os_windows_x86.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/os_cpu/windows_x86/vm/os_windows_x86.cpp Tue Mar 12 11:38:52 2013 +0100 @@ -70,7 +70,7 @@ extern LONG WINAPI topLevelExceptionFilter(_EXCEPTION_POINTERS* ); // Install a win32 structured exception handler around thread. -void os::os_exception_wrapper(java_call_t f, JavaValue* value, methodHandle* method, nmethod* nm, JavaCallArguments* args, Thread* thread) { +void os::os_exception_wrapper(java_call_t f, JavaValue* value, methodHandle* method, JavaCallArguments* args, Thread* thread) { __try { #ifndef AMD64 @@ -110,7 +110,7 @@ #endif // ASSERT #endif // !AMD64 - f(value, method, nm, args, thread); + f(value, method, args, thread); } __except(topLevelExceptionFilter((_EXCEPTION_POINTERS*)_exception_info())) { // Nothing to do. } @@ -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); }
--- a/src/os_cpu/windows_x86/vm/threadLS_windows_x86.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/os_cpu/windows_x86/vm/threadLS_windows_x86.cpp Tue Mar 12 11:38:52 2013 +0100 @@ -39,7 +39,7 @@ // up the offset from FS of the thread pointer. void ThreadLocalStorage::generate_code_for_get_thread() { os::os_exception_wrapper( (java_call_t)call_wrapper_dummy, - NULL, NULL, NULL, NULL, NULL); + NULL, NULL, NULL, NULL); } void ThreadLocalStorage::pd_init() { }
--- a/src/share/tools/IdealGraphVisualizer/Graal/src/com/sun/hotspot/igv/graal/filters/GraalCFGFilter.java Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/tools/IdealGraphVisualizer/Graal/src/com/sun/hotspot/igv/graal/filters/GraalCFGFilter.java Tue Mar 12 11:38:52 2013 +0100 @@ -45,7 +45,6 @@ Set<Connection> connectionsToRemove = new HashSet<>(); for (Figure f : d.getFigures()) { final String prop = f.getProperties().get("probability"); - if (prop == null) { figuresToRemove.add(f); } @@ -54,7 +53,15 @@ for (Figure f : d.getFigures()) { Properties p = f.getProperties(); - int predCount = Integer.parseInt(p.get("predecessorCount")); + int predCount; + String predCountString = p.get("predecessorCount"); + if (predCountString != null) { + predCount = Integer.parseInt(predCountString); + } else if (Boolean.parseBoolean(p.get("hasPredecessor"))) { + predCount = 1; + } else { + predCount = 0; + } for (InputSlot is : f.getInputSlots()) { if (is.getPosition() >= predCount && !"EndNode".equals(is.getProperties().get("class"))) { for (Connection c : is.getConnections()) {
--- a/src/share/tools/IdealGraphVisualizer/Graal/src/com/sun/hotspot/igv/graal/filters/GraalEdgeColorFilter.java Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/tools/IdealGraphVisualizer/Graal/src/com/sun/hotspot/igv/graal/filters/GraalEdgeColorFilter.java Tue Mar 12 11:38:52 2013 +0100 @@ -58,7 +58,10 @@ for (Figure f : figures) { Properties p = f.getProperties(); int predCount; - if (Boolean.parseBoolean(p.get("hasPredecessor"))) { + String predCountString = p.get("predecessorCount"); + if (predCountString != null) { + predCount = Integer.parseInt(predCountString); + } else if (Boolean.parseBoolean(p.get("hasPredecessor"))) { predCount = 1; } else { predCount = 0;
--- a/src/share/tools/whitebox/sun/hotspot/WhiteBox.java Tue Mar 12 11:38:24 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); -}
--- a/src/share/tools/whitebox/sun/hotspot/parser/DiagnosticCommand.java Tue Mar 12 11:38:24 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; - } -}
--- a/src/share/vm/adlc/adlparse.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/adlc/adlparse.cpp Tue Mar 12 11:38:52 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();
--- a/src/share/vm/adlc/formssel.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/adlc/formssel.cpp Tue Mar 12 11:38:52 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;
--- a/src/share/vm/asm/macroAssembler.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/asm/macroAssembler.hpp Tue Mar 12 11:38:52 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
--- a/src/share/vm/asm/macroAssembler.inline.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/asm/macroAssembler.inline.hpp Tue Mar 12 11:38:52 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
--- a/src/share/vm/c1/c1_CodeStubs.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/c1/c1_CodeStubs.hpp Tue Mar 12 11:38:52 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
--- a/src/share/vm/c1/c1_GraphBuilder.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/c1/c1_GraphBuilder.cpp Tue Mar 12 11:38:52 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");
--- a/src/share/vm/c1/c1_IR.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/c1/c1_IR.hpp Tue Mar 12 11:38:52 2013 +0100 @@ -240,8 +240,8 @@ // reexecute allowed only for the topmost frame bool reexecute = topmost ? should_reexecute() : false; bool return_oop = false; // This flag will be ignored since it used only for C2 with escape analysis. - methodHandle null_mh; - recorder->describe_scope(pc_offset, null_mh, scope()->method(), bci(), reexecute, false, is_method_handle_invoke, return_oop, locvals, expvals, monvals); + bool rethrow_exception = false; + recorder->describe_scope(pc_offset, methodHandle(), scope()->method(), bci(), reexecute, rethrow_exception, is_method_handle_invoke, return_oop, locvals, expvals, monvals); } };
--- a/src/share/vm/c1/c1_Instruction.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/c1/c1_Instruction.cpp Tue Mar 12 11:38:52 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?");
--- a/src/share/vm/c1/c1_LIR.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/c1/c1_LIR.cpp Tue Mar 12 11:38:52 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)); }
--- a/src/share/vm/c1/c1_LIRGenerator.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/c1/c1_LIRGenerator.cpp Tue Mar 12 11:38:52 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(); }
--- a/src/share/vm/ci/ciCallProfile.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/ci/ciCallProfile.hpp Tue Mar 12 11:38:52 2013 +0100 @@ -61,7 +61,6 @@ // Note: The following predicates return false for invalid profiles: bool has_receiver(int i) const { return _limit > i; } int morphism() const { return _morphism; } - int limit() const { return _limit; } int count() const { return _count; } int receiver_count(int i) {
--- a/src/share/vm/ci/ciEnv.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/ci/ciEnv.cpp Tue Mar 12 11:38:52 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);
--- a/src/share/vm/ci/ciField.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/ci/ciField.hpp Tue Mar 12 11:38:52 2013 +0100 @@ -166,8 +166,6 @@ // at each point of access. bool will_link(ciInstanceKlass* accessing_klass, Bytecodes::Code bc); - bool will_link_from_vm(ciInstanceKlass* accessing_klass, - Bytecodes::Code bc); // Java access flags bool is_public () { return flags().is_public(); }
--- a/src/share/vm/ci/ciInstanceKlass.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/ci/ciInstanceKlass.cpp Tue Mar 12 11:38:52 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();
--- a/src/share/vm/ci/ciMethod.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/ci/ciMethod.cpp Tue Mar 12 11:38:52 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",
--- a/src/share/vm/ci/ciMethod.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/ci/ciMethod.hpp Tue Mar 12 11:38:52 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);
--- a/src/share/vm/ci/ciMethodData.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/ci/ciMethodData.cpp Tue Mar 12 11:38:52 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();
--- a/src/share/vm/ci/ciObject.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/ci/ciObject.hpp Tue Mar 12 11:38:52 2013 +0100 @@ -65,14 +65,12 @@ ciObject(Handle h); ciObject(ciKlass* klass); -public: jobject handle() const { return _handle; } // Get the VM oop that this object holds. oop get_oop() const { assert(_handle != NULL, "null oop"); return JNIHandles::resolve_non_null(_handle); } -protected: void init_flags_from(oop x);
--- a/src/share/vm/ci/ciReplay.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/ci/ciReplay.cpp Tue Mar 12 11:38:52 2013 +0100 @@ -30,6 +30,7 @@ #include "memory/oopFactory.hpp" #include "memory/resourceArea.hpp" #include "utilities/copy.hpp" +#include "utilities/macros.hpp" #ifndef PRODUCT
--- a/src/share/vm/ci/ciSymbol.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/ci/ciSymbol.hpp Tue Mar 12 11:38:52 2013 +0100 @@ -48,7 +48,7 @@ private: const vmSymbols::SID _sid; - DEBUG_ONLY( bool sid_ok() { return true;/*vmSymbols::find_sid(get_symbol()) == _sid;*/ } ) + DEBUG_ONLY( bool sid_ok() { return vmSymbols::find_sid(get_symbol()) == _sid; } ) ciSymbol(Symbol* s); // normal case, for symbols not mentioned in vmSymbols ciSymbol(Symbol* s, vmSymbols::SID sid); // for use with vmSymbols
--- a/src/share/vm/classfile/classFileParser.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/classfile/classFileParser.cpp Tue Mar 12 11:38:52 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<AnnotationArray*>** methods_annotations, - Array<AnnotationArray*>** methods_parameter_annotations, - Array<AnnotationArray*>** methods_default_annotations, - Array<AnnotationArray*>** 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<AnnotationArray*>(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<AnnotationArray*>(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<AnnotationArray*>(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<AnnotationArray*>(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<int>* ClassFileParser::sort_methods(ClassLoaderData* loader_data, Array<Method*>* methods, - Array<AnnotationArray*>* methods_annotations, - Array<AnnotationArray*>* methods_parameter_annotations, - Array<AnnotationArray*>* methods_default_annotations, - Array<AnnotationArray*>* 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<AnnotationArray*>* methods_annotations = NULL; - Array<AnnotationArray*>* methods_parameter_annotations = NULL; - Array<AnnotationArray*>* methods_default_annotations = NULL; - Array<AnnotationArray*>* methods_type_annotations = NULL; Array<Method*>* 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<int>* 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
--- a/src/share/vm/classfile/classFileParser.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/classfile/classFileParser.hpp Tue Mar 12 11:38:52 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<Method*>* parse_methods(ClassLoaderData* loader_data, constantPoolHandle cp, bool is_interface, AccessFlags* promoted_flags, bool* has_final_method, - Array<AnnotationArray*>** methods_annotations, - Array<AnnotationArray*>** methods_parameter_annotations, - Array<AnnotationArray*>** methods_default_annotations, - Array<AnnotationArray*>** methods_type_annotations, bool* has_default_method, TRAPS); Array<int>* sort_methods(ClassLoaderData* loader_data, Array<Method*>* methods, - Array<AnnotationArray*>* methods_annotations, - Array<AnnotationArray*>* methods_parameter_annotations, - Array<AnnotationArray*>* methods_default_annotations, - Array<AnnotationArray*>* 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); }
--- a/src/share/vm/classfile/classLoader.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/classfile/classLoader.cpp Tue Mar 12 11:38:52 2013 +0100 @@ -442,23 +442,10 @@ void ClassLoader::setup_bootstrap_search_path() { assert(_first_entry == NULL, "should not setup bootstrap class search path twice"); char* sys_class_path = os::strdup(Arguments::get_sysclasspath()); -#ifdef GRAAL - char* compiler_class_path = os::strdup(Arguments::get_compilerclasspath()); -#endif if (TraceClassLoading && Verbose) { tty->print_cr("[Bootstrap loader class path=%s]", sys_class_path); -#ifdef GRAAL - tty->print_cr("[Compiler loader class path=%s]", compiler_class_path); -#endif } - setup_bootstrap_search_path(sys_class_path); -#ifdef GRAAL - setup_bootstrap_search_path(compiler_class_path); -#endif -} - -void ClassLoader::setup_bootstrap_search_path(char* sys_class_path) { int len = (int)strlen(sys_class_path); int end = 0; @@ -908,23 +895,7 @@ PerfClassTraceTime vmtimer(perf_sys_class_lookup_time(), ((JavaThread*) THREAD)->get_thread_stat()->perf_timers_addr(), PerfClassTraceTime::CLASS_LOAD); - ClassPathEntry* e = _first_entry; - while (e != NULL) { - stream = e->open_stream(name); - if (stream != NULL) { - break; - } - e = e->next(); - ++classpath_index; - } - } - - if (stream == NULL && !(THREAD->is_Compiler_thread())) { - classpath_index = 0; - PerfClassTraceTime vmtimer(perf_sys_class_lookup_time(), - ((JavaThread*) THREAD)->get_thread_stat()->perf_timers_addr(), - PerfClassTraceTime::CLASS_LOAD); - ClassPathEntry* e = _first_entry; + ClassPathEntry* e = _first_entry; while (e != NULL) { stream = e->open_stream(name); if (stream != NULL) {
--- a/src/share/vm/classfile/classLoader.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/classfile/classLoader.hpp Tue Mar 12 11:38:52 2013 +0100 @@ -206,7 +206,6 @@ // Initialization static void setup_meta_index(); static void setup_bootstrap_search_path(); - static void setup_bootstrap_search_path(char* sys_class_path); static void load_zip_library(); static void create_class_path_entry(char *path, struct stat st, ClassPathEntry **new_entry, bool lazy);
--- a/src/share/vm/classfile/classLoaderData.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/classfile/classLoaderData.cpp Tue Mar 12 11:38:52 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
--- a/src/share/vm/classfile/classLoaderData.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/classfile/classLoaderData.hpp Tue Mar 12 11:38:52 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();
--- a/src/share/vm/classfile/defaultMethods.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/classfile/defaultMethods.cpp Tue Mar 12 11:38:52 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<address>(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<AnnotationArray*>* original_annots[NUM_ARRAYS] = { NULL }; - Array<Method*>* 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<int>* original_ordering = klass->method_ordering(); Array<int>* merged_ordering = Universe::the_empty_int_array(); int new_size = klass->methods()->length() + new_methods->length(); - Array<AnnotationArray*>* merged_annots[NUM_ARRAYS]; - Array<Method*>* merged_methods = MetadataFactory::new_array<Method*>( 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<AnnotationArray*>( - 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<int>( 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);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/vm/classfile/metadataOnStackMark.cpp Tue Mar 12 11:38:52 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<Metadata*>* _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<Metadata*>(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); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/vm/classfile/metadataOnStackMark.hpp Tue Mar 12 11:38:52 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
--- a/src/share/vm/classfile/stackMapFrame.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/classfile/stackMapFrame.hpp Tue Mar 12 11:38:52 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(); } }
--- a/src/share/vm/classfile/systemDictionary.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/classfile/systemDictionary.cpp Tue Mar 12 11:38:52 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);
--- a/src/share/vm/classfile/systemDictionary.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/classfile/systemDictionary.hpp Tue Mar 12 11:38:52 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<<CEIL_LG_OPTION_LIMIT) }; @@ -436,7 +433,6 @@ static Klass* check_klass_Pre( Klass* k) { return check_klass(k); } static Klass* check_klass_Pre_JSR292(Klass* k) { return EnableInvokeDynamic ? check_klass(k) : k; } static Klass* check_klass_Opt( Klass* k) { return k; } - static Klass* check_klass_Opt_Kernel(Klass* k) { return k; } //== Opt static Klass* check_klass_Opt_Only_JDK15(Klass* k) { assert(JDK_Version::is_gte_jdk15x_version(), "JDK 1.5 only"); return k;
--- a/src/share/vm/classfile/verifier.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/classfile/verifier.cpp Tue Mar 12 11:38:52 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 @@ -61,7 +61,8 @@ # include "bytes_ppc.hpp" #endif -#define NOFAILOVER_MAJOR_VERSION 51 +#define NOFAILOVER_MAJOR_VERSION 51 +#define STATIC_METHOD_IN_INTERFACE_MAJOR_VERSION 52 // Access to external entry for VerifyClassCodes - old byte code verifier @@ -2317,6 +2318,11 @@ types = (1 << JVM_CONSTANT_InterfaceMethodref) | (1 << JVM_CONSTANT_Methodref); break; + case Bytecodes::_invokestatic: + types = (_klass->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; }
--- a/src/share/vm/classfile/vmSymbols.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/classfile/vmSymbols.hpp Tue Mar 12 11:38:52 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") \
--- a/src/share/vm/code/codeBlob.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/code/codeBlob.cpp Tue Mar 12 11:38:52 2013 +0100 @@ -39,7 +39,6 @@ #include "runtime/sharedRuntime.hpp" #include "runtime/vframe.hpp" #include "services/memoryService.hpp" -#include "utilities/machineCodePrinter.hpp" #ifdef TARGET_ARCH_x86 # include "nativeInst_x86.hpp" #endif @@ -134,11 +133,10 @@ cb->copy_code_and_locs_to(this); set_oop_maps(oop_maps); _frame_size = frame_size; -#if defined(COMPILER1) || defined(GRAAL) - +#ifdef COMPILER1 // probably wrong for tiered assert(_frame_size >= -1, "must use frame size or -1 for runtime stubs"); -#endif // COMPILER1 || GRAAL +#endif // COMPILER1 } @@ -345,10 +343,6 @@ trace_new_stub(stub, "RuntimeStub - ", stub_name); - if (PrintMachineCodeToFile) { - MachineCodePrinter::print(stub); - } - return stub; } @@ -384,7 +378,9 @@ _unpack_offset = unpack_offset; _unpack_with_exception = unpack_with_exception_offset; _unpack_with_reexecution = unpack_with_reexecution_offset; +#ifdef COMPILER1 _unpack_with_exception_in_tls = -1; +#endif }
--- a/src/share/vm/code/compiledIC.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/code/compiledIC.cpp Tue Mar 12 11:38:52 2013 +0100 @@ -95,7 +95,7 @@ // Don't use ic_destination for this test since that forwards // through ICBuffer instead of returning the actual current state of // the CompiledIC. - if (is_icholder_entry(_ic_call->destination())) { + if (is_icholder_entry(_ic_call->destination()) GRAAL_ONLY(&& _value != NULL)) { // When patching for the ICStub case the cached value isn't // overwritten until the ICStub copied into the CompiledIC during // the next safepoint. Make sure that the CompiledICHolder* is @@ -126,6 +126,13 @@ _ic_call->set_destination_mt_safe(entry_point); } +#ifdef GRAAL + if (_value == NULL) { + // Can happen when Graal converted a virtual call into an invoke special based on static analysis. + return; + } +#endif + if (is_optimized() || is_icstub) { // Optimized call sites don't have a cache value and ICStub call // sites only change the entry point. Changing the value in that @@ -265,12 +272,14 @@ // Check if we are calling into our own codeblob (i.e., to a stub) CodeBlob* cb = CodeCache::find_blob(_ic_call->instruction_address()); address dest = ic_destination(); +#ifndef GRAAL #ifdef ASSERT { CodeBlob* db = CodeCache::find_blob_unsafe(dest); assert(!db->is_adapter_blob(), "must use stub!"); } #endif /* ASSERT */ +#endif is_call_to_interpreted = cb->contains(dest); } return is_call_to_interpreted; @@ -552,6 +561,12 @@ void CompiledStaticCall::set_to_interpreted(methodHandle callee, address entry) { address stub=find_stub(); +#ifdef GRAAL + if (stub == NULL) { + set_destination_mt_safe(entry); + return; + } +#endif assert(stub!=NULL, "stub not found"); if (TraceICs) { @@ -702,9 +717,11 @@ // Verify stub address stub = find_stub(); +#ifndef GRAAL assert(stub != NULL, "no stub found for static call"); NativeMovConstReg* method_holder = nativeMovConstReg_at(stub); // creation also verifies the object NativeJump* jump = nativeJump_at(method_holder->next_instruction_address()); +#endif // Verify state assert(is_clean() || is_call_to_compiled() || is_call_to_interpreted(), "sanity check");
--- a/src/share/vm/code/debugInfo.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/code/debugInfo.cpp Tue Mar 12 11:38:52 2013 +0100 @@ -77,11 +77,7 @@ enum { LOCATION_CODE = 0, CONSTANT_INT_CODE = 1, CONSTANT_OOP_CODE = 2, CONSTANT_LONG_CODE = 3, CONSTANT_DOUBLE_CODE = 4, - OBJECT_CODE = 5, OBJECT_ID_CODE = 6, -#ifdef GRAAL - DEFERRED_READ_CODE = 7, DEFERRED_WRITE_CODE = 8 -#endif // GRAAL -}; + OBJECT_CODE = 5, OBJECT_ID_CODE = 6 }; ScopeValue* ScopeValue::read_from(DebugInfoReadStream* stream) { ScopeValue* result = NULL; @@ -93,10 +89,6 @@ case CONSTANT_DOUBLE_CODE: result = new ConstantDoubleValue(stream); break; case OBJECT_CODE: result = stream->read_object_value(); break; case OBJECT_ID_CODE: result = stream->get_cached_object(); break; -#ifdef GRAAL - case DEFERRED_READ_CODE: result = new DeferredReadValue(stream); break; - case DEFERRED_WRITE_CODE: result = new DeferredWriteValue(stream); break; -#endif // GRAAL default: ShouldNotReachHere(); } return result; @@ -117,63 +109,6 @@ location().print_on(st); } -#ifdef GRAAL - -// DeferredLocationValue - -DeferredLocationValue::DeferredLocationValue(DebugInfoReadStream* stream) { - _base = read_from(stream); - _index = read_from(stream); - _scale = stream->read_int(); - _disp = stream->read_long(); -} - -void DeferredLocationValue::write_on(DebugInfoWriteStream* stream) { - _base->write_on(stream); - _index->write_on(stream); - stream->write_int(_scale); - stream->write_long(_disp); -} - -void DeferredLocationValue::print_on(outputStream* st) const { - _base->print_on(st); - _index->print_on(st); - st->print("%i %i", _scale, _disp); -} - -// DeferredReadValue - -DeferredReadValue::DeferredReadValue(DebugInfoReadStream* stream) -: DeferredLocationValue(stream) { -} - -void DeferredReadValue::write_on(DebugInfoWriteStream* st) { - DeferredLocationValue::write_on(st); -} - -void DeferredReadValue::print_on(outputStream* st) const { - DeferredLocationValue::print_on(st); -} - -// DeferredWriteValue - -DeferredWriteValue::DeferredWriteValue(DebugInfoReadStream* stream) -: DeferredLocationValue(stream) { - _value = read_from(stream); -} - -void DeferredWriteValue::write_on(DebugInfoWriteStream* st) { - DeferredLocationValue::write_on(st); - _value->write_on(st); -} - -void DeferredWriteValue::print_on(outputStream* st) const { - DeferredLocationValue::print_on(st); - _value->print_on(st); -} - -#endif // GRAAL - // ObjectValue void ObjectValue::read_object(DebugInfoReadStream* stream) {
--- a/src/share/vm/code/debugInfo.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/code/debugInfo.hpp Tue Mar 12 11:38:52 2013 +0100 @@ -61,11 +61,6 @@ // Serialization of debugging information virtual void write_on(DebugInfoWriteStream* stream) = 0; static ScopeValue* read_from(DebugInfoReadStream* stream); - -#ifdef GRAAL - // Printing - virtual void print_on(outputStream* st) const = 0; -#endif // GRAAL }; @@ -88,64 +83,6 @@ void print_on(outputStream* st) const; }; -#ifdef GRAAL - -class DeferredLocationValue: public ScopeValue { -private: - ScopeValue* _base; - ScopeValue* _index; - jint _scale; - jlong _disp; -public: - DeferredLocationValue(ScopeValue* base, ScopeValue* index, jint scale, jlong disp) - : _base(base), _index(index), _scale(scale), _disp(disp) { } - - ScopeValue* base() { return _base; } - ScopeValue* index() { return _index; } - jint scale() { return _scale; } - jlong disp() { return _disp; } - - // Serialization of debugging information - DeferredLocationValue(DebugInfoReadStream* stream); - void write_on(DebugInfoWriteStream* stream); - - // Printing - void print_on(outputStream* st) const; -}; - - -class DeferredReadValue: public DeferredLocationValue { -public: - DeferredReadValue(ScopeValue* base, ScopeValue* index, jint scale, jint disp) - : DeferredLocationValue(base, index, scale, disp) { } - - // Serialization of debugging information - DeferredReadValue(DebugInfoReadStream* stream); - void write_on(DebugInfoWriteStream* stream); - - // Printing - void print_on(outputStream* st) const; -}; - -class DeferredWriteValue: public DeferredLocationValue { -private: - ScopeValue* _value; -public: - DeferredWriteValue(ScopeValue* base, ScopeValue* index, jint scale, jint disp, ScopeValue* value) - : DeferredLocationValue(base, index, scale, disp), _value(value) { } - - ScopeValue* value() { return _value; } - - // Serialization of debugging information - DeferredWriteValue(DebugInfoReadStream* stream); - void write_on(DebugInfoWriteStream* stream); - - // Printing - void print_on(outputStream* st) const; -}; - -#endif // GRAAL - // An ObjectValue describes an object eliminated by escape analysis.
--- a/src/share/vm/code/debugInfoRec.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/code/debugInfoRec.cpp Tue Mar 12 11:38:52 2013 +0100 @@ -213,29 +213,6 @@ return result; } -#ifdef GRAAL - -int DebugInformationRecorder::serialize_deferred_writes(GrowableArray<DeferredWriteValue*>* deferred_writes) { - if (deferred_writes == NULL || deferred_writes->is_empty()) return DebugInformationRecorder::serialized_null; - assert(_recording_state == rs_safepoint, "must be recording a safepoint"); - int result = stream()->position(); - assert(result != serialized_null, "sanity"); - stream()->write_int(deferred_writes->length()); - for (int index = 0; index < deferred_writes->length(); index++) { - deferred_writes->at(index)->write_on(stream()); - } - - // (See comment below on DebugInformationRecorder::describe_scope.) - int shared_result = find_sharable_decode_offset(result); - if (shared_result != serialized_null) { - stream()->set_position(result); - result = shared_result; - } - - return result; -} - -#endif // GRAAL #ifndef PRODUCT // These variables are put into one block to reduce relocations @@ -312,11 +289,7 @@ bool return_oop, DebugToken* locals, DebugToken* expressions, - DebugToken* monitors -#ifdef GRAAL - , DebugToken* deferred_writes -#endif // GRAAL - ) { + DebugToken* monitors) { assert(_recording_state != rs_null, "nesting of recording calls"); PcDesc* last_pd = last_pc(); assert(last_pd->pc_offset() == pc_offset, "must be last pc"); @@ -355,9 +328,6 @@ stream()->write_int((intptr_t) locals); stream()->write_int((intptr_t) expressions); stream()->write_int((intptr_t) monitors); -#ifdef GRAAL - stream()->write_int((intptr_t) deferred_writes); -#endif // GRAAL // Here's a tricky bit. We just wrote some bytes. // Wouldn't it be nice to find that we had already @@ -439,14 +409,6 @@ return (DebugToken*) (intptr_t) serialize_monitor_values(monitors); } -#ifdef GRAAL - -DebugToken* DebugInformationRecorder::create_deferred_writes(GrowableArray<DeferredWriteValue*>* deferred_writes) { - assert(!recorders_frozen(), "not frozen yet"); - return (DebugToken*) (intptr_t) serialize_deferred_writes(deferred_writes); -} - -#endif // GRAAL int DebugInformationRecorder::data_size() { debug_only(mark_recorders_frozen()); // mark it "frozen" for asserts
--- a/src/share/vm/code/debugInfoRec.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/code/debugInfoRec.hpp Tue Mar 12 11:38:52 2013 +0100 @@ -107,11 +107,7 @@ bool return_oop = false, DebugToken* locals = NULL, DebugToken* expressions = NULL, - DebugToken* monitors = NULL -#ifdef GRAAL - , DebugToken* deferred_writes = NULL -#endif // GRAAL - ); + DebugToken* monitors = NULL); void dump_object_pool(GrowableArray<ScopeValue*>* objects); @@ -124,9 +120,6 @@ // helper fuctions for describe_scope to enable sharing DebugToken* create_scope_values(GrowableArray<ScopeValue*>* values); DebugToken* create_monitor_values(GrowableArray<MonitorValue*>* monitors); -#ifdef GRAAL - DebugToken* create_deferred_writes(GrowableArray<DeferredWriteValue*>* deferred_writes); -#endif // GRAAL // returns the size of the generated scopeDescs. int data_size(); @@ -201,9 +194,6 @@ int serialize_monitor_values(GrowableArray<MonitorValue*>* monitors); int serialize_scope_values(GrowableArray<ScopeValue*>* values); -#ifdef GRAAL - int serialize_deferred_writes(GrowableArray<DeferredWriteValue*>* deferred_writes); -#endif // GRAAL int find_sharable_decode_offset(int stream_offset); #ifndef PRODUCT
--- a/src/share/vm/code/dependencies.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/code/dependencies.cpp Tue Mar 12 11:38:52 2013 +0100 @@ -563,6 +563,7 @@ _size_in_bytes = bytes.position(); } + const char* Dependencies::_dep_name[TYPE_LIMIT] = { "end_marker", "evol_method",
--- a/src/share/vm/code/icBuffer.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/code/icBuffer.cpp Tue Mar 12 11:38:52 2013 +0100 @@ -96,8 +96,8 @@ void ICStub::verify() { } -void ICStub::print_on(outputStream* st) { - st->print_cr("ICStub: site: " INTPTR_FORMAT, _ic_site); +void ICStub::print() { + tty->print_cr("ICStub: site: " INTPTR_FORMAT, _ic_site); } #endif
--- a/src/share/vm/code/icBuffer.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/code/icBuffer.hpp Tue Mar 12 11:38:52 2013 +0100 @@ -75,8 +75,8 @@ void* cached_value() const; // cached_value for stub // Debugging - void verify() PRODUCT_RETURN; - void print_on(outputStream* st) PRODUCT_RETURN; + void verify() PRODUCT_RETURN; + void print() PRODUCT_RETURN; // Creation friend ICStub* ICStub_from_destination_address(address destination_address);
--- a/src/share/vm/code/nmethod.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/code/nmethod.cpp Tue Mar 12 11:38:52 2013 +0100 @@ -42,8 +42,6 @@ #include "utilities/dtrace.hpp" #include "utilities/events.hpp" #include "utilities/xmlstream.hpp" -#include "utilities/debug.hpp" -#include "utilities/machineCodePrinter.hpp" #ifdef SHARK #include "shark/sharkCompiler.hpp" #endif @@ -126,6 +124,7 @@ // PrintC1Statistics, PrintOptoStatistics, LogVMOutput, and LogCompilation. // (In the latter two cases, they like other stats are printed to the log only.) +#ifndef PRODUCT // These variables are put into one block to reduce relocations // and make it simpler to print from the debugger. static @@ -215,6 +214,7 @@ pc_desc_tests, pc_desc_searches, pc_desc_adds); } } nmethod_stats; +#endif //PRODUCT //--------------------------------------------------------------------------------- @@ -490,6 +490,7 @@ _compiler = NULL; #ifdef GRAAL _graal_installed_code = NULL; + _triggered_deoptimizations = NULL; #endif #ifdef HAVE_DTRACE_H _trap_offset = 0; @@ -520,13 +521,9 @@ code_buffer, frame_size, basic_lock_owner_sp_offset, basic_lock_sp_offset, oop_maps); - if (nm != NULL) nmethod_stats.note_native_nmethod(nm); + NOT_PRODUCT(if (nm != NULL) nmethod_stats.note_native_nmethod(nm)); if (PrintAssembly && nm != NULL) Disassembler::decode(nm); - - if (PrintMachineCodeToFile) { - MachineCodePrinter::print(nm); - } } // verify nmethod debug_only(if (nm) nm->verify();) // might block @@ -558,7 +555,7 @@ nm = new (nmethod_size) nmethod(method(), nmethod_size, &offsets, code_buffer, frame_size); - if (nm != NULL) nmethod_stats.note_nmethod(nm); + NOT_PRODUCT(if (nm != NULL) nmethod_stats.note_nmethod(nm)); if (PrintAssembly && nm != NULL) Disassembler::decode(nm); } @@ -589,7 +586,8 @@ int comp_level, GrowableArray<jlong>* leaf_graph_ids #ifdef GRAAL - , Handle installed_code + , Handle installed_code, + Handle triggered_deoptimizations #endif ) { @@ -617,7 +615,8 @@ comp_level, leaf_graph_ids #ifdef GRAAL - , installed_code + , installed_code, + triggered_deoptimizations #endif ); if (nm != NULL) { @@ -637,13 +636,9 @@ InstanceKlass::cast(klass)->add_dependent_nmethod(nm); } } - if (nm != NULL) nmethod_stats.note_nmethod(nm); + NOT_PRODUCT(if (nm != NULL) nmethod_stats.note_nmethod(nm)); if (PrintAssembly && nm != NULL) Disassembler::decode(nm); - - if (nm != NULL && PrintMachineCodeToFile) { - MachineCodePrinter::print(nm); - } } // verify nmethod @@ -847,7 +842,8 @@ int comp_level, GrowableArray<jlong>* leaf_graph_ids #ifdef GRAAL - , Handle installed_code + , Handle installed_code, + Handle triggered_deoptimizations #endif ) : CodeBlob("nmethod", code_buffer, sizeof(nmethod), @@ -874,6 +870,7 @@ #ifdef GRAAL _graal_installed_code = installed_code(); + _triggered_deoptimizations = (typeArrayOop)triggered_deoptimizations(); #endif if (compiler->is_graal()) { // Graal might not produce any stub sections @@ -1693,8 +1690,16 @@ #ifdef GRAAL // Follow Graal method - if (_graal_installed_code != NULL && can_unload(is_alive, (oop*)&_graal_installed_code, unloading_occurred)) { - return; + if (_graal_installed_code != NULL) { + if (HotSpotInstalledCode::isDefault(_graal_installed_code)) { + if (!is_alive->do_object_b(_graal_installed_code)) { + _graal_installed_code = NULL; + } + } else { + if (can_unload(is_alive, (oop*)&_graal_installed_code, unloading_occurred)) { + return; + } + } } #endif @@ -1819,8 +1824,8 @@ // really alive. void nmethod::verify_metadata_loaders(address low_boundary, BoolObjectClosure* is_alive) { #ifdef ASSERT - RelocIterator iter(this, low_boundary); - while (iter.next()) { + RelocIterator iter(this, low_boundary); + while (iter.next()) { // static_stub_Relocations may have dangling references to // Method*s so trim them out here. Otherwise it looks like // compiled code is maintaining a link to dead metadata. @@ -1829,13 +1834,11 @@ CompiledIC* cic = CompiledIC_at(iter.reloc()); if (!cic->is_call_to_interpreted()) { static_call_addr = iter.addr(); - cic->set_to_clean(); } } else if (iter.type() == relocInfo::static_call_type) { CompiledStaticCall* csc = compiledStaticCall_at(iter.reloc()); if (!csc->is_call_to_interpreted()) { static_call_addr = iter.addr(); - csc->set_to_clean(); } } if (static_call_addr != NULL) { @@ -1920,9 +1923,12 @@ } #ifdef GRAAL - if (_graal_installed_code != NULL) { + if(_graal_installed_code != NULL) { f->do_oop((oop*) &_graal_installed_code); } + if (_triggered_deoptimizations != NULL) { + f->do_oop((oop*) &_triggered_deoptimizations); + } #endif RelocIterator iter(this, low_boundary); @@ -2512,9 +2518,7 @@ // information in a table. break; } -#ifndef GRAAL assert(stub == NULL || stub_contains(stub), "static call stub outside stub section"); -#endif } } @@ -3006,8 +3010,6 @@ ImplicitExceptionTable(this).print(code_begin()); } -#endif // PRODUCT - void nmethod::print_statistics() { ttyLocker ttyl; if (xtty != NULL) xtty->head("statistics type='nmethod'"); @@ -3019,18 +3021,4 @@ if (xtty != NULL) xtty->tail("statistics"); } -#ifdef GRAAL -void DebugScopedNMethod::print_on(outputStream* st) { - if (_nm != NULL) { - st->print("nmethod@%p", _nm); - Method* method = _nm->method(); - if (method != NULL) { - char holder[O_BUFLEN]; - char nameAndSig[O_BUFLEN]; - method->method_holder()->name()->as_C_string(holder, O_BUFLEN); - method->name_and_sig_as_C_string(nameAndSig, O_BUFLEN); - st->print(" - %s::%s", holder, nameAndSig); - } - } -} -#endif +#endif // PRODUCT
--- a/src/share/vm/code/nmethod.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/code/nmethod.hpp Tue Mar 12 11:38:52 2013 +0100 @@ -119,6 +119,7 @@ #ifdef GRAAL // Needed to keep nmethods alive that are not the default nmethod for the associated Method. oop _graal_installed_code; + typeArrayOop _triggered_deoptimizations; #endif // To support simple linked-list chaining of nmethods: @@ -271,7 +272,8 @@ int comp_level, GrowableArray<jlong>* leaf_graph_ids #ifdef GRAAL - , Handle installed_code + , Handle installed_code, + Handle triggered_deoptimizations #endif ); @@ -291,7 +293,7 @@ // Inform external interfaces that a compiled method has been unloaded void post_compiled_method_unload(); - // Initialize fields to their default values + // Initailize fields to their default values void init_defaults(); public: @@ -312,7 +314,8 @@ int comp_level, GrowableArray<jlong>* leaf_graph_ids = NULL #ifdef GRAAL - , Handle installed_code = NULL + , Handle installed_code = Handle(), + Handle triggered_deoptimizations = Handle() #endif ); @@ -357,9 +360,6 @@ bool is_compiled_by_c2() const; bool is_compiled_by_shark() const; - -#define CHECK_POSITIVE(val) assert(val, "should be positive") - // boundaries for different parts address consts_begin () const { return header_begin() + _consts_offset ; } address consts_end () const { return header_begin() + code_offset() ; } @@ -367,8 +367,8 @@ address insts_end () const { return header_begin() + _stub_offset ; } address stub_begin () const { return header_begin() + _stub_offset ; } address stub_end () const { return header_begin() + _oops_offset ; } - address exception_begin () const { assert(_exception_offset >= 0, "no exception handler"); return header_begin() + _exception_offset ; } - address deopt_handler_begin () const { assert(_deoptimize_offset >= 0, "no deopt handler"); return header_begin() + _deoptimize_offset ; } + address exception_begin () const { return header_begin() + _exception_offset ; } + address deopt_handler_begin () const { return header_begin() + _deoptimize_offset ; } address deopt_mh_handler_begin() const { return header_begin() + _deoptimize_mh_offset ; } address unwind_handler_begin () const { return _unwind_handler_offset != -1 ? (header_begin() + _unwind_handler_offset) : NULL; } oop* oops_begin () const { return (oop*) (header_begin() + _oops_offset) ; } @@ -689,7 +689,7 @@ // Prints a comment for one native instruction (reloc info, pc desc) void print_code_comment_on(outputStream* st, int column, address begin, address end); - static void print_statistics(); + static void print_statistics() PRODUCT_RETURN; // Compiler task identification. Note that all OSR methods // are numbered in an independent sequence if CICountOSR is true, @@ -774,19 +774,4 @@ } }; -#ifdef GRAAL -class DebugScopedNMethod : public DebugScopedValue { -private: - nmethod* _nm; -public: - DebugScopedNMethod(const char* file, int line, nmethod* nm) : DebugScopedValue(file, line), _nm(nm) {} - void print_on(outputStream* st); -}; -#define DS_NMETHOD(nm) DebugScopedNMethod __dsnm__(__FILE__, __LINE__, nm) -#define DS_NMETHOD1(name, nm) DebugScopedNMethod name(__FILE__, __LINE__, nm) -#else -#define DS_NMETHOD(nm) do {} while (0) -#define DS_NMETHOD1(name, nm) do {} while (0) -#endif - #endif // SHARE_VM_CODE_NMETHOD_HPP
--- a/src/share/vm/code/pcDesc.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/code/pcDesc.hpp Tue Mar 12 11:38:52 2013 +0100 @@ -81,8 +81,7 @@ bool is_same_info(const PcDesc* pd) { return _scope_decode_offset == pd->_scope_decode_offset && _obj_decode_offset == pd->_obj_decode_offset && - _flags == pd->_flags - ; + _flags == pd->_flags; } bool is_method_handle_invoke() const { return (_flags & PCDESC_is_method_handle_invoke) != 0; }
--- a/src/share/vm/code/scopeDesc.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/code/scopeDesc.cpp Tue Mar 12 11:38:52 2013 +0100 @@ -73,9 +73,6 @@ _locals_decode_offset = DebugInformationRecorder::serialized_null; _expressions_decode_offset = DebugInformationRecorder::serialized_null; _monitors_decode_offset = DebugInformationRecorder::serialized_null; -#ifdef GRAAL - _deferred_writes_decode_offset = DebugInformationRecorder::serialized_null; -#endif // GRAAL } else { // decode header DebugInfoReadStream* stream = stream_at(decode_offset()); @@ -88,9 +85,6 @@ _locals_decode_offset = stream->read_int(); _expressions_decode_offset = stream->read_int(); _monitors_decode_offset = stream->read_int(); -#ifdef GRAAL - _deferred_writes_decode_offset = stream->read_int(); -#endif // GRAAL } } @@ -132,25 +126,6 @@ return result; } -#ifdef GRAAL - -GrowableArray<DeferredWriteValue*>* ScopeDesc::decode_deferred_writes(int decode_offset) { - if (decode_offset == DebugInformationRecorder::serialized_null) return NULL; - DebugInfoReadStream* stream = stream_at(decode_offset); - int length = stream->read_int(); - GrowableArray<DeferredWriteValue*>* result = new GrowableArray<DeferredWriteValue*> (length); - for (int index = 0; index < length; index++) { - result->push(new DeferredWriteValue(stream)); - } - return result; -} - -GrowableArray<DeferredWriteValue*>* ScopeDesc::deferred_writes() { - return decode_deferred_writes(_deferred_writes_decode_offset); -} - -#endif // GRAAL - DebugInfoReadStream* ScopeDesc::stream_at(int decode_offset) const { return new DebugInfoReadStream(_code, decode_offset, _objects); } @@ -261,19 +236,6 @@ } } #endif // COMPILER2 || GRAAL -#ifdef GRAAL - // deferred writes - { GrowableArray<DeferredWriteValue*>* l = ((ScopeDesc*) this)->deferred_writes(); - if (l != NULL) { - st->print_cr(" Deferred writes"); - for (int index = 0; index < l->length(); index++) { - st->print(" - @%d: ", index); - l->at(index)->print_on(st); - st->cr(); - } - } - } -#endif } #endif
--- a/src/share/vm/code/scopeDesc.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/code/scopeDesc.hpp Tue Mar 12 11:38:52 2013 +0100 @@ -78,9 +78,6 @@ GrowableArray<ScopeValue*>* expressions(); GrowableArray<MonitorValue*>* monitors(); GrowableArray<ScopeValue*>* objects(); -#ifdef GRAAL - GrowableArray<DeferredWriteValue*>* deferred_writes(); -#endif // GRAAL // Stack walking, returns NULL if this is the outer most scope. ScopeDesc* sender() const; @@ -110,9 +107,6 @@ int _locals_decode_offset; int _expressions_decode_offset; int _monitors_decode_offset; -#ifdef GRAAL - int _deferred_writes_decode_offset; -#endif // GRAAL // Object pool GrowableArray<ScopeValue*>* _objects; @@ -125,9 +119,6 @@ GrowableArray<ScopeValue*>* decode_scope_values(int decode_offset); GrowableArray<MonitorValue*>* decode_monitor_values(int decode_offset); GrowableArray<ScopeValue*>* decode_object_values(int decode_offset); -#ifdef GRAAL - GrowableArray<DeferredWriteValue*>* decode_deferred_writes(int decode_offset); -#endif // GRAAL DebugInfoReadStream* stream_at(int decode_offset) const;
--- a/src/share/vm/code/stubs.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/code/stubs.cpp Tue Mar 12 11:38:52 2013 +0100 @@ -254,9 +254,10 @@ guarantee(_queue_begin != _queue_end || n == 0, "buffer indices must be the same"); } -void StubQueue::print_on(outputStream* st) const { + +void StubQueue::print() { MutexLockerEx lock(_mutex); for (Stub* s = first(); s != NULL; s = next(s)) { - stub_print(s, st); + stub_print(s); } }
--- a/src/share/vm/code/stubs.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/code/stubs.hpp Tue Mar 12 11:38:52 2013 +0100 @@ -107,21 +107,20 @@ public: // Initialization/finalization virtual void initialize(Stub* self, int size, - CodeComments& comments) = 0; // called after creation (called twice if allocated via (request, commit)) - virtual void finalize(Stub* self) = 0; // called before deallocation + CodeComments& comments) = 0; // called after creation (called twice if allocated via (request, commit)) + virtual void finalize(Stub* self) = 0; // called before deallocation // General info/converters - virtual int size(Stub* self) const = 0; // the total size of the stub in bytes (must be a multiple of CodeEntryAlignment) - virtual int code_size_to_size(int code_size) const = 0; // computes the total stub size in bytes given the code size in bytes + virtual int size(Stub* self) const = 0; // the total size of the stub in bytes (must be a multiple of CodeEntryAlignment) + virtual int code_size_to_size(int code_size) const = 0; // computes the total stub size in bytes given the code size in bytes // Code info - virtual address code_begin(Stub* self) const = 0; // points to the first code byte - virtual address code_end(Stub* self) const = 0; // points to the first byte after the code + virtual address code_begin(Stub* self) const = 0; // points to the first code byte + virtual address code_end(Stub* self) const = 0; // points to the first byte after the code // Debugging - virtual void verify(Stub* self) const = 0; // verifies the stub - NOT_PRODUCT(using AllocatedObj::print_on;) - virtual void print_on(Stub* self, outputStream* st) const = 0; // prints information about the stub + virtual void verify(Stub* self) = 0; // verifies the stub + virtual void print(Stub* self) = 0; // prints information about the stub }; @@ -129,29 +128,28 @@ // class, forwarding stub interface calls to the corresponding // stub calls. -#define DEF_STUB_INTERFACE(stub) \ - class stub##Interface: public StubInterface { \ - private: \ - static stub* cast(Stub* self) { return (stub*)self; } \ - \ - public: \ - /* Initialization/finalization */ \ - virtual void initialize(Stub* self, int size, \ - CodeComments& comments) { cast(self)->initialize(size, comments); } \ - virtual void finalize(Stub* self) { cast(self)->finalize(); } \ - \ - /* General info */ \ - virtual int size(Stub* self) const { return cast(self)->size(); } \ - virtual int code_size_to_size(int code_size) const { return stub::code_size_to_size(code_size); } \ - \ - /* Code info */ \ - virtual address code_begin(Stub* self) const { return cast(self)->code_begin(); } \ - virtual address code_end(Stub* self) const { return cast(self)->code_end(); } \ - \ - /* Debugging */ \ - virtual void verify(Stub* self) const { cast(self)->verify(); } \ - NOT_PRODUCT(using AllocatedObj::print_on;) \ - virtual void print_on(Stub* self, outputStream* st) const { cast(self)->print_on(st); } \ +#define DEF_STUB_INTERFACE(stub) \ + class stub##Interface: public StubInterface { \ + private: \ + static stub* cast(Stub* self) { return (stub*)self; } \ + \ + public: \ + /* Initialization/finalization */ \ + virtual void initialize(Stub* self, int size, \ + CodeComments& comments) { cast(self)->initialize(size, comments); } \ + virtual void finalize(Stub* self) { cast(self)->finalize(); } \ + \ + /* General info */ \ + virtual int size(Stub* self) const { return cast(self)->size(); } \ + virtual int code_size_to_size(int code_size) const { return stub::code_size_to_size(code_size); } \ + \ + /* Code info */ \ + virtual address code_begin(Stub* self) const { return cast(self)->code_begin(); } \ + virtual address code_end(Stub* self) const { return cast(self)->code_end(); } \ + \ + /* Debugging */ \ + virtual void verify(Stub* self) { cast(self)->verify(); } \ + virtual void print(Stub* self) { cast(self)->print(); } \ }; @@ -184,7 +182,7 @@ bool stub_contains(Stub* s, address pc) const { return _stub_interface->code_begin(s) <= pc && pc < _stub_interface->code_end(s); } int stub_code_size_to_size(int code_size) const { return _stub_interface->code_size_to_size(code_size); } void stub_verify(Stub* s) { _stub_interface->verify(s); } - void stub_print(Stub* s, outputStream* st) const { _stub_interface->print_on(s, st); } + void stub_print(Stub* s) { _stub_interface->print(s); } static void register_queue(StubQueue*); @@ -228,9 +226,8 @@ address stub_code_end(Stub* s) const { return _stub_interface->code_end(s); } // Debugging/printing - void verify(); // verifies the stub queue - virtual void print() const { print_on(tty); } - virtual void print_on(outputStream* st) const; + void verify(); // verifies the stub queue + void print(); // prints information about the stub queue }; #endif // SHARE_VM_CODE_STUBS_HPP
--- a/src/share/vm/compiler/compileBroker.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/compiler/compileBroker.cpp Tue Mar 12 11:38:52 2013 +0100 @@ -44,9 +44,6 @@ #include "runtime/sharedRuntime.hpp" #include "runtime/sweeper.hpp" #include "utilities/dtrace.hpp" -#ifdef GRAAL -#include "graal/graalCompiler.hpp" -#endif #include "utilities/events.hpp" #ifdef COMPILER1 #include "c1/c1_Compiler.hpp" @@ -1421,7 +1418,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;
--- a/src/share/vm/compiler/oopMap.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/compiler/oopMap.hpp Tue Mar 12 11:38:52 2013 +0100 @@ -47,7 +47,7 @@ class OopMapValue: public StackObj { friend class VMStructs; private: - int _value; + short _value; int value() const { return _value; } void set_value(int value) { _value = value; } short _content_reg; @@ -55,7 +55,7 @@ public: // Constants enum { type_bits = 5, - register_bits = BitsPerJavaInteger - type_bits }; + register_bits = BitsPerShort - type_bits }; enum { type_shift = 0, register_shift = type_bits };
--- a/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp Tue Mar 12 11:38:52 2013 +0100 @@ -102,7 +102,7 @@ // temporarily disabled). switch (dictionaryChoice) { case FreeBlockDictionary<FreeChunk>::dictionaryBinaryTree: - _dictionary = new BinaryTreeDictionary<FreeChunk, AdaptiveFreeList>(mr); + _dictionary = new AFLBinaryTreeDictionary(mr); break; case FreeBlockDictionary<FreeChunk>::dictionarySplayTree: case FreeBlockDictionary<FreeChunk>::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<FreeChunk>::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<FreeChunk>::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<FreeChunk>::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<FreeChunk>::atLeast); if (fc == NULL) { return NULL; }
--- a/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp Tue Mar 12 11:38:52 2013 +0100 @@ -131,7 +131,7 @@ LinearAllocBlock _smallLinearAllocBlock; FreeBlockDictionary<FreeChunk>::DictionaryChoice _dictionaryChoice; - FreeBlockDictionary<FreeChunk>* _dictionary; // ptr to dictionary for large size blocks + AFLBinaryTreeDictionary* _dictionary; // ptr to dictionary for large size blocks AdaptiveFreeList<FreeChunk> _indexedFreeList[IndexSetSize]; // indexed array for small size blocks
--- a/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp Tue Mar 12 11:38:52 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 {
--- a/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp Tue Mar 12 11:38:52 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,
--- a/src/share/vm/gc_implementation/concurrentMarkSweep/vmStructs_cms.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/gc_implementation/concurrentMarkSweep/vmStructs_cms.hpp Tue Mar 12 11:38:52 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<FreeChunk, AdaptiveFreeList> 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<FreeChunk>) \ 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<FreeChunk>) \ - declare_type(AFLBinaryTreeDictionary, FreeBlockDictionary<FreeChunk>) + declare_toplevel_type(FreeBlockDictionary<FreeChunk>) #define VM_INT_CONSTANTS_CMS(declare_constant) \ declare_constant(Generation::ConcurrentMarkSweep) \
--- a/src/share/vm/gc_implementation/g1/concurrentMark.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/gc_implementation/g1/concurrentMark.cpp Tue Mar 12 11:38:52 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 <class T> 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 {
--- a/src/share/vm/gc_implementation/g1/concurrentMark.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/gc_implementation/g1/concurrentMark.hpp Tue Mar 12 11:38:52 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
--- a/src/share/vm/gc_implementation/g1/concurrentMarkThread.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/gc_implementation/g1/concurrentMarkThread.cpp Tue Mar 12 11:38:52 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); } }
--- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Tue Mar 12 11:38:52 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<oop>(40, true); - _preserved_marks_of_objs = - new (ResourceObj::C_HEAP, mtGC) GrowableArray<markOop>(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); } }
--- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp Tue Mar 12 11:38:52 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<oop>* _objs_with_preserved_marks; - GrowableArray<markOop>* _preserved_marks_of_objs; + // Together, these store an object with a preserved mark, and its mark value. + Stack<oop, mtGC> _objs_with_preserved_marks; + Stack<markOop, mtGC> _preserved_marks_of_objs; // Preserve the mark of "obj", if necessary, in preparation for its mark // word being overwritten with a self-forwarding-pointer.
--- a/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp Tue Mar 12 11:38:52 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);
--- a/src/share/vm/gc_implementation/g1/g1SATBCardTableModRefBS.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/gc_implementation/g1/g1SATBCardTableModRefBS.hpp Tue Mar 12 11:38:52 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
--- a/src/share/vm/gc_implementation/g1/g1_globals.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/gc_implementation/g1/g1_globals.hpp Tue Mar 12 11:38:52 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") \ \
--- a/src/share/vm/gc_implementation/g1/heapRegion.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/gc_implementation/g1/heapRegion.hpp Tue Mar 12 11:38:52 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
--- a/src/share/vm/gc_implementation/shared/allocationStats.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/gc_implementation/shared/allocationStats.cpp Tue Mar 12 11:38:52 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.
--- a/src/share/vm/gc_implementation/shared/allocationStats.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/gc_implementation/shared/allocationStats.hpp Tue Mar 12 11:38:52 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
--- a/src/share/vm/gc_implementation/shared/concurrentGCThread.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/gc_implementation/shared/concurrentGCThread.hpp Tue Mar 12 11:38:52 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;
--- a/src/share/vm/gc_implementation/shared/gSpaceCounters.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/gc_implementation/shared/gSpaceCounters.cpp Tue Mar 12 11:38:52 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,
--- a/src/share/vm/gc_implementation/shared/gSpaceCounters.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/gc_implementation/shared/gSpaceCounters.hpp Tue Mar 12 11:38:52 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;
--- a/src/share/vm/gc_implementation/shared/gcAdaptivePolicyCounters.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/gc_implementation/shared/gcAdaptivePolicyCounters.hpp Tue Mar 12 11:38:52 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.
--- a/src/share/vm/gc_implementation/shared/hSpaceCounters.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/gc_implementation/shared/hSpaceCounters.hpp Tue Mar 12 11:38:52 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;
--- a/src/share/vm/gc_implementation/shared/immutableSpace.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/gc_implementation/shared/immutableSpace.cpp Tue Mar 12 11:38:52 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();
--- a/src/share/vm/gc_implementation/shared/isGCActiveMark.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/gc_implementation/shared/isGCActiveMark.hpp Tue Mar 12 11:38:52 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
--- a/src/share/vm/gc_implementation/shared/markSweep.inline.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/gc_implementation/shared/markSweep.inline.hpp Tue Mar 12 11:38:52 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
--- a/src/share/vm/gc_implementation/shared/mutableNUMASpace.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/gc_implementation/shared/mutableNUMASpace.hpp Tue Mar 12 11:38:52 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
--- a/src/share/vm/gc_implementation/shared/mutableSpace.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/gc_implementation/shared/mutableSpace.cpp Tue Mar 12 11:38:52 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 &&
--- a/src/share/vm/gc_implementation/shared/spaceCounters.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/gc_implementation/shared/spaceCounters.cpp Tue Mar 12 11:38:52 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) :
--- a/src/share/vm/gc_implementation/shared/spaceCounters.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/gc_implementation/shared/spaceCounters.hpp Tue Mar 12 11:38:52 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;
--- a/src/share/vm/gc_implementation/shared/vmGCOperations.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/gc_implementation/shared/vmGCOperations.cpp Tue Mar 12 11:38:52 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 */); }
--- a/src/share/vm/gc_implementation/shared/vmGCOperations.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/gc_implementation/shared/vmGCOperations.hpp Tue Mar 12 11:38:52 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;} };
--- a/src/share/vm/graal/graalCodeInstaller.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/graal/graalCodeInstaller.cpp Tue Mar 12 11:38:52 2013 +0100 @@ -126,6 +126,10 @@ assert((Klass*) prim == klass, err_msg("%s @ %p != %p", klass->name()->as_C_string(), klass, prim)); int index = oop_recorder->find_index(klass); TRACE_graal_3("metadata[%d of %d] = %s", index, oop_recorder->metadata_count(), klass->name()->as_C_string()); + } else if (obj->is_a(HotSpotResolvedJavaMethod::klass())) { + Method* method = (Method*) (address) HotSpotResolvedJavaMethod::metaspaceMethod(obj); + int index = oop_recorder->find_index(method); + TRACE_graal_3("metadata[%d of %d] = %s", index, oop_recorder->metadata_count(), method->name()->as_C_string()); } else { assert(java_lang_String::is_instance(obj), err_msg("unexpected annotation type (%s) for constant %ld (%p) of kind %c", obj->klass()->name()->as_C_string(), prim, prim, kind)); @@ -322,7 +326,7 @@ } // constructor used to create a method -CodeInstaller::CodeInstaller(Handle& comp_result, methodHandle method, GraalEnv::CodeInstallResult& result, nmethod*& nm, Handle installed_code) { +CodeInstaller::CodeInstaller(Handle& comp_result, methodHandle method, GraalEnv::CodeInstallResult& result, nmethod*& nm, Handle installed_code, Handle triggered_deoptimizations) { GraalCompiler::initialize_buffer_blob(); CodeBuffer buffer(JavaThread::current()->get_buffer_blob()); jobject comp_result_obj = JNIHandles::make_local(comp_result()); @@ -340,7 +344,7 @@ GrowableArray<jlong>* leaf_graph_ids = get_leaf_graph_ids(comp_result); result = GraalEnv::register_method(method, nm, entry_bci, &_offsets, _custom_stack_area_offset, &buffer, stack_slots, _debug_recorder->_oopmaps, &_exception_handler_table, - &_implicit_exception_table, GraalCompiler::instance(), _debug_recorder, _dependencies, NULL, -1, true, false, leaf_graph_ids, installed_code); + GraalCompiler::instance(), _debug_recorder, _dependencies, NULL, -1, true, false, leaf_graph_ids, installed_code, triggered_deoptimizations); method->clear_queued_for_compilation(); } @@ -571,13 +575,9 @@ DebugToken* expressions_token = _debug_recorder->create_scope_values(expressions); DebugToken* monitors_token = _debug_recorder->create_monitor_values(monitors); - GrowableArray<DeferredWriteValue*>* deferred_writes = new GrowableArray<DeferredWriteValue*> (); -// deferred_writes->append(new DeferredWriteValue(new LocationValue(Location::new_reg_loc(Location::lng, rax->as_VMReg())), new ConstantIntValue(0), 0, 100, new ConstantIntValue(123))); - DebugToken* deferred_writes_token = _debug_recorder->create_deferred_writes(deferred_writes); - bool throw_exception = BytecodeFrame::rethrowException(frame) == JNI_TRUE; - _debug_recorder->describe_scope(pc_offset, method, NULL, bci, reexecute, throw_exception, false, false, locals_token, expressions_token, monitors_token, deferred_writes_token); + _debug_recorder->describe_scope(pc_offset, method, NULL, bci, reexecute, throw_exception, false, false, locals_token, expressions_token, monitors_token); } void CodeInstaller::site_Safepoint(CodeBuffer& buffer, jint pc_offset, oop site) { @@ -617,7 +617,6 @@ NativeInstruction* inst = nativeInstruction_at(_instructions->start() + pc_offset); jint next_pc_offset = 0x0; - bool is_call_reg = false; if (inst->is_call() || inst->is_jump()) { assert(NativeCall::instruction_size == (int)NativeJump::instruction_size, "unexpected size"); next_pc_offset = pc_offset + NativeCall::instruction_size; @@ -630,10 +629,8 @@ } else if (inst->is_call_reg()) { // the inlined vtable stub contains a "call register" instruction assert(hotspot_method != NULL, "only valid for virtual calls"); - is_call_reg = true; next_pc_offset = pc_offset + ((NativeCallReg *) inst)->next_instruction_offset(); } else { - tty->print_cr("at pc_offset %d", pc_offset); fatal("unsupported type of instruction for call site"); } @@ -688,9 +685,8 @@ TRACE_graal_3("method call"); switch (_next_call_type) { - case MARK_INLINE_INVOKEVIRTUAL: { + case MARK_INLINE_INVOKE: break; - } case MARK_INVOKEVIRTUAL: case MARK_INVOKEINTERFACE: { assert(method == NULL || !method->is_static(), "cannot call static method with invokeinterface"); @@ -710,13 +706,11 @@ } case MARK_INVOKESPECIAL: { assert(method == NULL || !method->is_static(), "cannot call static method with invokespecial"); - NativeCall* call = nativeCall_at(_instructions->start() + pc_offset); call->set_destination(SharedRuntime::get_resolve_opt_virtual_call_stub()); _instructions->relocate(call->instruction_address(), relocInfo::opt_virtual_call_type, Assembler::call32_operand); break; } - case MARK_INVOKE_INVALID: default: fatal("invalid _next_call_type value"); break; @@ -816,14 +810,6 @@ case MARK_DEOPT_HANDLER_ENTRY: _offsets.set_value(CodeOffsets::Deopt, pc_offset); break; - case MARK_STATIC_CALL_STUB: { - _instructions->relocate(instruction, metadata_Relocation::spec_for_immediate()); - assert(references->length() == 1, "static call stub needs one reference"); - oop ref = ((oop*) references->base(T_OBJECT))[0]; - address call_pc = _instructions->start() + CompilationResult_Site::pcOffset(ref); - _instructions->relocate(instruction, static_stub_Relocation::spec(call_pc)); - break; - } case MARK_INVOKEVIRTUAL: case MARK_INVOKEINTERFACE: { // Convert the initial value of the Klass* slot in an inline cache @@ -832,16 +818,12 @@ assert(n_copy->data() == 0, "inline cache Klass* initial value should be 0L"); n_copy->set_data((intptr_t)Universe::non_oop_word()); } - case MARK_INLINE_INVOKEVIRTUAL: - case MARK_INVOKE_INVALID: + case MARK_INLINE_INVOKE: + case MARK_INVOKESTATIC: case MARK_INVOKESPECIAL: - case MARK_INVOKESTATIC: _next_call_type = (MarkId) id; _invoke_mark_pc = instruction; break; - case MARK_IMPLICIT_NULL: - _implicit_exception_table.append(pc_offset, pc_offset); - break; case MARK_POLL_NEAR: { NativeInstruction* ni = nativeInstruction_at(instruction); int32_t* disp = (int32_t*) Assembler::locate_operand(instruction, Assembler::disp32_operand);
--- a/src/share/vm/graal/graalCodeInstaller.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/graal/graalCodeInstaller.hpp Tue Mar 12 11:38:52 2013 +0100 @@ -31,24 +31,21 @@ private: // these need to correspond to Marks.java enum MarkId { - MARK_VERIFIED_ENTRY = 0x0001, - MARK_UNVERIFIED_ENTRY = 0x0002, - MARK_OSR_ENTRY = 0x0003, - //MARK_UNWIND_ENTRY = 0x0004, - MARK_EXCEPTION_HANDLER_ENTRY = 0x0005, - MARK_DEOPT_HANDLER_ENTRY = 0x0006, - MARK_STATIC_CALL_STUB = 0x1000, - MARK_INVOKE_INVALID = 0x2000, - MARK_INVOKEINTERFACE = 0x2001, - MARK_INVOKESTATIC = 0x2002, - MARK_INVOKESPECIAL = 0x2003, - MARK_INVOKEVIRTUAL = 0x2004, - MARK_INLINE_INVOKEVIRTUAL = 0x2005, - MARK_IMPLICIT_NULL = 0x3000, - MARK_POLL_NEAR = 0x3001, - MARK_POLL_RETURN_NEAR = 0x3002, - MARK_POLL_FAR = 0x3003, - MARK_POLL_RETURN_FAR = 0x3004 + MARK_VERIFIED_ENTRY = 1, + MARK_UNVERIFIED_ENTRY = 2, + MARK_OSR_ENTRY = 3, + MARK_EXCEPTION_HANDLER_ENTRY = 4, + MARK_DEOPT_HANDLER_ENTRY = 5, + MARK_INVOKEINTERFACE = 6, + MARK_INVOKEVIRTUAL = 7, + MARK_INVOKESTATIC = 8, + MARK_INVOKESPECIAL = 9, + MARK_INLINE_INVOKE = 10, + MARK_POLL_NEAR = 11, + MARK_POLL_RETURN_NEAR = 12, + MARK_POLL_FAR = 13, + MARK_POLL_RETURN_FAR = 14, + MARK_INVOKE_INVALID = -1 }; Arena _arena; @@ -77,12 +74,11 @@ DebugInformationRecorder* _debug_recorder; Dependencies* _dependencies; ExceptionHandlerTable _exception_handler_table; - ImplicitExceptionTable _implicit_exception_table; public: // constructor used to create a method - CodeInstaller(Handle& comp_result, methodHandle method, GraalEnv::CodeInstallResult& result, nmethod*& nm, Handle installed_code); + CodeInstaller(Handle& comp_result, methodHandle method, GraalEnv::CodeInstallResult& result, nmethod*& nm, Handle installed_code, Handle triggered_deoptimizations); // constructor used to create a stub CodeInstaller(Handle& target_method, BufferBlob*& blob, jlong& id);
--- a/src/share/vm/graal/graalCompiler.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/graal/graalCompiler.cpp Tue Mar 12 11:38:52 2013 +0100 @@ -159,11 +159,10 @@ assert(_initialized, "must already be initialized"); ResourceMark rm; - assert(JavaThread::current()->env() == NULL, "ciEnv should be null"); - JavaThread::current()->set_compiling(true); + JavaThread::current()->set_is_compiling(true); Handle holder = GraalCompiler::createHotSpotResolvedObjectType(method, CHECK); jboolean success = VMToCompiler::compileMethod(method(), holder, entry_bci, blocking, method->graal_priority()); - JavaThread::current()->set_compiling(false); + JavaThread::current()->set_is_compiling(false); if (success != JNI_TRUE) { method->clear_queued_for_compilation(); CompilationPolicy::policy()->delay_compilation(method());
--- a/src/share/vm/graal/graalCompilerToVM.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/graal/graalCompilerToVM.cpp Tue Mar 12 11:38:52 2013 +0100 @@ -407,10 +407,6 @@ } else if (tag.is_klass() || tag.is_unresolved_klass()) { Handle type = GraalCompiler::get_JavaType(cp, index, cp->pool_holder(), CHECK_NULL); result = type(); - } else if (tag.is_object()) { - oop obj = cp->object_at(index); - assert(obj->is_instance(), "must be an instance"); - result = VMToCompiler::createConstantObject(obj, CHECK_NULL); } else { tty->print("unknown constant pool tag (%s) at cpi %d in %s: ", tag.internal_name(), index, cp->pool_holder()->name()->as_C_string()); ShouldNotReachHere(); @@ -706,37 +702,34 @@ set_int("layoutHelperHeaderSizeMask", Klass::_lh_header_size_mask); set_int("layoutHelperOffset", in_bytes(Klass::layout_helper_offset())); - set_stub("debugStub", (address)warning); - set_stub("instanceofStub", GraalRuntime::entry_for(GraalRuntime::graal_slow_subtype_check_id)); - set_stub("newInstanceStub", GraalRuntime::entry_for(GraalRuntime::graal_new_instance_id)); - set_stub("newArrayStub", GraalRuntime::entry_for(GraalRuntime::graal_new_array_id)); - set_stub("newMultiArrayStub", GraalRuntime::entry_for(GraalRuntime::graal_new_multi_array_id)); - set_stub("identityHashCodeStub", GraalRuntime::entry_for(GraalRuntime::graal_identity_hash_code_id)); - set_stub("threadIsInterruptedStub", GraalRuntime::entry_for(GraalRuntime::graal_thread_is_interrupted_id)); + set_stub("newInstanceStub", GraalRuntime::entry_for(GraalRuntime::new_instance_id)); + set_stub("newArrayStub", GraalRuntime::entry_for(GraalRuntime::new_array_id)); + set_stub("newMultiArrayStub", GraalRuntime::entry_for(GraalRuntime::new_multi_array_id)); + set_stub("identityHashCodeStub", GraalRuntime::entry_for(GraalRuntime::identity_hash_code_id)); + set_stub("threadIsInterruptedStub", GraalRuntime::entry_for(GraalRuntime::thread_is_interrupted_id)); set_stub("inlineCacheMissStub", SharedRuntime::get_ic_miss_stub()); - set_stub("handleExceptionStub", GraalRuntime::entry_for(GraalRuntime::graal_handle_exception_nofpu_id)); + set_stub("handleExceptionStub", GraalRuntime::entry_for(GraalRuntime::handle_exception_nofpu_id)); set_stub("handleDeoptStub", SharedRuntime::deopt_blob()->unpack()); - set_stub("monitorEnterStub", GraalRuntime::entry_for(GraalRuntime::graal_monitorenter_id)); - set_stub("monitorExitStub", GraalRuntime::entry_for(GraalRuntime::graal_monitorexit_id)); - set_stub("verifyOopStub", GraalRuntime::entry_for(GraalRuntime::graal_verify_oop_id)); - set_stub("vmErrorStub", GraalRuntime::entry_for(GraalRuntime::graal_vm_error_id)); + set_stub("monitorEnterStub", GraalRuntime::entry_for(GraalRuntime::monitorenter_id)); + set_stub("monitorExitStub", GraalRuntime::entry_for(GraalRuntime::monitorexit_id)); + set_stub("verifyOopStub", GraalRuntime::entry_for(GraalRuntime::verify_oop_id)); + set_stub("vmErrorStub", GraalRuntime::entry_for(GraalRuntime::vm_error_id)); set_stub("deoptimizeStub", SharedRuntime::deopt_blob()->uncommon_trap()); - set_stub("unwindExceptionStub", GraalRuntime::entry_for(GraalRuntime::graal_unwind_exception_call_id)); - set_stub("osrMigrationEndStub", GraalRuntime::entry_for(GraalRuntime::graal_OSR_migration_end_id)); - set_stub("registerFinalizerStub", GraalRuntime::entry_for(GraalRuntime::graal_register_finalizer_id)); - set_stub("setDeoptInfoStub", GraalRuntime::entry_for(GraalRuntime::graal_set_deopt_info_id)); - set_stub("createNullPointerExceptionStub", GraalRuntime::entry_for(GraalRuntime::graal_create_null_pointer_exception_id)); - set_stub("createOutOfBoundsExceptionStub", GraalRuntime::entry_for(GraalRuntime::graal_create_out_of_bounds_exception_id)); + set_stub("unwindExceptionStub", GraalRuntime::entry_for(GraalRuntime::unwind_exception_call_id)); + set_stub("osrMigrationEndStub", GraalRuntime::entry_for(GraalRuntime::OSR_migration_end_id)); + set_stub("registerFinalizerStub", GraalRuntime::entry_for(GraalRuntime::register_finalizer_id)); + set_stub("createNullPointerExceptionStub", GraalRuntime::entry_for(GraalRuntime::create_null_pointer_exception_id)); + set_stub("createOutOfBoundsExceptionStub", GraalRuntime::entry_for(GraalRuntime::create_out_of_bounds_exception_id)); set_stub("javaTimeMillisStub", CAST_FROM_FN_PTR(address, os::javaTimeMillis)); set_stub("javaTimeNanosStub", CAST_FROM_FN_PTR(address, os::javaTimeNanos)); - set_stub("arithmeticFremStub", GraalRuntime::entry_for(GraalRuntime::graal_arithmetic_frem_id)); - set_stub("arithmeticDremStub", GraalRuntime::entry_for(GraalRuntime::graal_arithmetic_drem_id)); + set_stub("arithmeticFremStub", GraalRuntime::entry_for(GraalRuntime::arithmetic_frem_id)); + set_stub("arithmeticDremStub", GraalRuntime::entry_for(GraalRuntime::arithmetic_drem_id)); set_stub("arithmeticSinStub", CAST_FROM_FN_PTR(address, SharedRuntime::dsin)); set_stub("arithmeticCosStub", CAST_FROM_FN_PTR(address, SharedRuntime::dcos)); set_stub("arithmeticTanStub", CAST_FROM_FN_PTR(address, SharedRuntime::dtan)); - set_stub("logPrimitiveStub", GraalRuntime::entry_for(GraalRuntime::graal_log_primitive_id)); - set_stub("logObjectStub", GraalRuntime::entry_for(GraalRuntime::graal_log_object_id)); - set_stub("logPrintfStub", GraalRuntime::entry_for(GraalRuntime::graal_log_printf_id)); + set_stub("logPrimitiveStub", GraalRuntime::entry_for(GraalRuntime::log_primitive_id)); + set_stub("logObjectStub", GraalRuntime::entry_for(GraalRuntime::log_object_id)); + set_stub("logPrintfStub", GraalRuntime::entry_for(GraalRuntime::log_printf_id)); set_stub("aescryptEncryptBlockStub", StubRoutines::aescrypt_encryptBlock()); set_stub("aescryptDecryptBlockStub", StubRoutines::aescrypt_decryptBlock()); set_stub("cipherBlockChainingEncryptAESCryptStub", StubRoutines::cipherBlockChaining_encryptAESCrypt()); @@ -798,15 +791,16 @@ C2V_END -C2V_VMENTRY(jint, installCode0, (JNIEnv *jniEnv, jobject, jobject compResult, jobject installed_code, jobject info)) +C2V_VMENTRY(jint, installCode0, (JNIEnv *jniEnv, jobject, jobject compResult, jobject installed_code, jobject info, jobject triggered_deoptimizations)) ResourceMark rm; HandleMark hm; Handle compResultHandle = JNIHandles::resolve(compResult); nmethod* nm = NULL; methodHandle method = getMethodFromHotSpotMethod(HotSpotCompilationResult::method(compResult)); Handle installed_code_handle = JNIHandles::resolve(installed_code); + Handle triggered_deoptimizations_handle = JNIHandles::resolve(triggered_deoptimizations); GraalEnv::CodeInstallResult result; - CodeInstaller installer(compResultHandle, method, result, nm, installed_code_handle); + CodeInstaller installer(compResultHandle, method, result, nm, installed_code_handle, triggered_deoptimizations_handle); if (result != GraalEnv::ok) { assert(nm == NULL, "should be"); @@ -884,7 +878,8 @@ THROW_0(vmSymbols::MethodInvalidatedException()); } - JavaCalls::call(&result, mh, nm, &jca, CHECK_NULL); + jca.set_alternative_target(nm); + JavaCalls::call(&result, mh, &jca, CHECK_NULL); if (jap.get_ret_type() == T_VOID) { return NULL; @@ -913,7 +908,8 @@ THROW_0(vmSymbols::MethodInvalidatedException()); } - JavaCalls::call(&result, method, nm, &args, CHECK_NULL); + args.set_alternative_target(nm); + JavaCalls::call(&result, method, &args, CHECK_NULL); return JNIHandles::make_local((oop) result.get_jobject()); C2V_END @@ -1101,7 +1097,7 @@ {CC"getMetaspaceConstructor", CC"("REFLECT_CONSTRUCTOR"["HS_RESOLVED_TYPE")"METASPACE_METHOD, FN_PTR(getMetaspaceConstructor)}, {CC"getJavaField", CC"("REFLECT_FIELD")"HS_RESOLVED_FIELD, FN_PTR(getJavaField)}, {CC"initializeConfiguration", CC"("HS_CONFIG")V", FN_PTR(initializeConfiguration)}, - {CC"installCode0", CC"("HS_COMP_RESULT HS_INSTALLED_CODE HS_CODE_INFO")I", FN_PTR(installCode0)}, + {CC"installCode0", CC"("HS_COMP_RESULT HS_INSTALLED_CODE HS_CODE_INFO"[Z)I", FN_PTR(installCode0)}, {CC"disassembleNative", CC"([BJ)"STRING, FN_PTR(disassembleNative)}, {CC"disassembleNMethod", CC"(J)"STRING, FN_PTR(disassembleNMethod)}, {CC"executeCompiledMethod", CC"("METASPACE_METHOD NMETHOD OBJECT OBJECT OBJECT")"OBJECT, FN_PTR(executeCompiledMethod)},
--- a/src/share/vm/graal/graalEnv.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/graal/graalEnv.cpp Tue Mar 12 11:38:52 2013 +0100 @@ -43,6 +43,7 @@ #include "runtime/sharedRuntime.hpp" #include "utilities/dtrace.hpp" #include "graal/graalRuntime.hpp" +#include "graal/graalJavaAccess.hpp" // ------------------------------------------------------------------ // Note: the logic of this method should mirror the logic of @@ -410,7 +411,6 @@ int frame_words, OopMapSet* oop_map_set, ExceptionHandlerTable* handler_table, - ImplicitExceptionTable* inc_table, AbstractCompiler* compiler, DebugInformationRecorder* debug_info, Dependencies* dependencies, @@ -419,7 +419,8 @@ bool has_debug_info, bool has_unsafe_access, GrowableArray<jlong>* leaf_graph_ids, - Handle installed_code) { + Handle installed_code, + Handle triggered_deoptimizations) { GRAAL_EXCEPTION_CONTEXT; NMethodSweeper::possibly_sweep(); nm = NULL; @@ -455,7 +456,7 @@ //code_buffer->free_blob(); return GraalEnv::dependencies_failed; } - + ImplicitExceptionTable implicit_tbl; nm = nmethod::new_nmethod(method, compile_id, entry_bci, @@ -463,8 +464,8 @@ orig_pc_offset, debug_info, dependencies, code_buffer, frame_words, oop_map_set, - handler_table, inc_table, - compiler, comp_level, leaf_graph_ids, installed_code); + handler_table, &implicit_tbl, + compiler, comp_level, leaf_graph_ids, installed_code, triggered_deoptimizations); // Free codeBlobs //code_buffer->free_blob(); @@ -493,7 +494,7 @@ // (Put nm into the task handle *before* publishing to the Java heap.) if (task != NULL) task->set_code(nm); - if (installed_code.is_null()) { + if (HotSpotInstalledCode::isDefault(installed_code())) { if (entry_bci == InvocationEntryBci) { if (TieredCompilation) { // If there is an old version we're done with it
--- a/src/share/vm/graal/graalEnv.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/graal/graalEnv.hpp Tue Mar 12 11:38:52 2013 +0100 @@ -138,7 +138,6 @@ int frame_words, OopMapSet* oop_map_set, ExceptionHandlerTable* handler_table, - ImplicitExceptionTable* inc_table, AbstractCompiler* compiler, DebugInformationRecorder* debug_info, Dependencies* dependencies, @@ -147,7 +146,8 @@ bool has_debug_info, bool has_unsafe_access, GrowableArray<jlong>* leaf_graph_ids, - Handle installed_code); + Handle installed_code, + Handle triggered_deoptimizations); // converts the Klass* representing the holder of a method into a // InstanceKlass*. This is needed since the holder of a method in
--- a/src/share/vm/graal/graalGlobals.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/graal/graalGlobals.hpp Tue Mar 12 11:38:52 2013 +0100 @@ -52,9 +52,6 @@ product(bool, BootstrapGraal, GRAALVM_ONLY(true) NOT_GRAALVM(false), \ "Bootstrap Graal before running Java main method") \ \ - product(ccstr, GraalClassPath, NULL, \ - "Use this path, zip, or jar, to locate Graal-specific classes") \ - \ product(intx, TraceGraal, 0, \ "Trace level for Graal") \ \
--- a/src/share/vm/graal/graalJavaAccess.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/graal/graalJavaAccess.hpp Tue Mar 12 11:38:52 2013 +0100 @@ -75,6 +75,7 @@ start_class(HotSpotInstalledCode) \ long_field(HotSpotInstalledCode, nmethod) \ oop_field(HotSpotInstalledCode, method, "Lcom/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod;") \ + boolean_field(HotSpotInstalledCode, isDefault) \ end_class \ start_class(HotSpotCodeInfo) \ long_field(HotSpotCodeInfo, start) \
--- a/src/share/vm/graal/graalRuntime.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/graal/graalRuntime.cpp Tue Mar 12 11:38:52 2013 +0100 @@ -127,16 +127,14 @@ // Make sure that stubs that need oopmaps have them switch (id) { // These stubs don't need to have an oopmap - case graal_slow_subtype_check_id: #if defined(SPARC) || defined(PPC) - case graal_handle_exception_nofpu_id: // Unused on sparc + case handle_exception_nofpu_id: // Unused on sparc #endif - case graal_verify_oop_id: - case graal_unwind_exception_call_id: - case graal_OSR_migration_end_id: - case graal_arithmetic_frem_id: - case graal_arithmetic_drem_id: - case graal_set_deopt_info_id: + case verify_oop_id: + case unwind_exception_call_id: + case OSR_migration_end_id: + case arithmetic_frem_id: + case arithmetic_drem_id: break; // All other stubs should have oopmaps @@ -442,17 +440,17 @@ return continuation; } -JRT_ENTRY(void, GraalRuntime::graal_create_null_exception(JavaThread* thread)) +JRT_ENTRY(void, GraalRuntime::create_null_exception(JavaThread* thread)) thread->set_vm_result(Exceptions::new_exception(thread, vmSymbols::java_lang_NullPointerException(), NULL)()); JRT_END -JRT_ENTRY(void, GraalRuntime::graal_create_out_of_bounds_exception(JavaThread* thread, jint index)) +JRT_ENTRY(void, GraalRuntime::create_out_of_bounds_exception(JavaThread* thread, jint index)) char message[jintAsStringSize]; sprintf(message, "%d", index); thread->set_vm_result(Exceptions::new_exception(thread, vmSymbols::java_lang_ArrayIndexOutOfBoundsException(), message)()); JRT_END -JRT_ENTRY_NO_ASYNC(void, GraalRuntime::graal_monitorenter(JavaThread* thread, oopDesc* obj, BasicLock* lock)) +JRT_ENTRY_NO_ASYNC(void, GraalRuntime::monitorenter(JavaThread* thread, oopDesc* obj, BasicLock* lock)) if (TraceGraal >= 3) { char type[O_BUFLEN]; obj->klass()->name()->as_C_string(type, O_BUFLEN); @@ -484,7 +482,7 @@ JRT_END -JRT_LEAF(void, GraalRuntime::graal_monitorexit(JavaThread* thread, oopDesc* obj, BasicLock* lock)) +JRT_LEAF(void, GraalRuntime::monitorexit(JavaThread* thread, oopDesc* obj, BasicLock* lock)) assert(thread == JavaThread::current(), "threads must correspond"); assert(thread->last_Java_sp(), "last_Java_sp must be set"); // monitorexit is non-blocking (leaf routine) => no exceptions can be thrown @@ -516,7 +514,7 @@ } JRT_END -JRT_ENTRY(void, GraalRuntime::graal_log_object(JavaThread* thread, oop obj, jint flags)) +JRT_ENTRY(void, GraalRuntime::log_object(JavaThread* thread, oop obj, jint flags)) bool string = mask_bits_are_true(flags, LOG_OBJECT_STRING); bool address = mask_bits_are_true(flags, LOG_OBJECT_ADDRESS); bool newline = mask_bits_are_true(flags, LOG_OBJECT_NEWLINE); @@ -538,7 +536,7 @@ } JRT_END -JRT_ENTRY(void, GraalRuntime::graal_vm_error(JavaThread* thread, oop where, oop format, jlong value)) +JRT_ENTRY(void, GraalRuntime::vm_error(JavaThread* thread, oop where, oop format, jlong value)) ResourceMark rm; assert(where == NULL || java_lang_String::is_instance(where), "must be"); const char *error_msg = where == NULL ? "<internal Graal error>" : java_lang_String::as_utf8_string(where); @@ -552,14 +550,14 @@ report_vm_error(__FILE__, __LINE__, error_msg, detail_msg); JRT_END -JRT_ENTRY(void, GraalRuntime::graal_log_printf(JavaThread* thread, oop format, jlong v1, jlong v2, jlong v3)) +JRT_ENTRY(void, GraalRuntime::log_printf(JavaThread* thread, oop format, jlong v1, jlong v2, jlong v3)) ResourceMark rm; assert(format != NULL && java_lang_String::is_instance(format), "must be"); char *buf = java_lang_String::as_utf8_string(format); tty->print(buf, v1, v2, v3); JRT_END -JRT_ENTRY(void, GraalRuntime::graal_log_primitive(JavaThread* thread, jchar typeChar, jlong value, jboolean newline)) +JRT_ENTRY(void, GraalRuntime::log_primitive(JavaThread* thread, jchar typeChar, jlong value, jboolean newline)) union { jlong l; jdouble d; @@ -582,11 +580,11 @@ } JRT_END -JRT_ENTRY(jint, GraalRuntime::graal_identity_hash_code(JavaThread* thread, oop obj)) +JRT_ENTRY(jint, GraalRuntime::identity_hash_code(JavaThread* thread, oop obj)) return (jint) obj->identity_hash(); JRT_END -JRT_ENTRY(jboolean, GraalRuntime::graal_thread_is_interrupted(JavaThread* thread, oop receiver, jboolean clear_interrupted)) +JRT_ENTRY(jboolean, GraalRuntime::thread_is_interrupted(JavaThread* thread, oop receiver, jboolean clear_interrupted)) // Ensure that the C++ Thread and OSThread structures aren't freed before we operate Handle receiverHandle(thread, receiver); MutexLockerEx ml(thread->threadObj() == receiver ? NULL : Threads_lock);
--- a/src/share/vm/graal/graalRuntime.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/graal/graalRuntime.hpp Tue Mar 12 11:38:52 2013 +0100 @@ -81,28 +81,26 @@ // runtime routines needed by code code generated // by Graal. #define GRAAL_STUBS(stub, last_entry) \ - stub(graal_register_finalizer) \ - stub(graal_new_instance) \ - stub(graal_new_array) \ - stub(graal_new_multi_array) \ - stub(graal_handle_exception_nofpu) /* optimized version that does not preserve fpu registers */ \ - stub(graal_slow_subtype_check) \ - stub(graal_unwind_exception_call) \ - stub(graal_OSR_migration_end) \ - stub(graal_arithmetic_frem) \ - stub(graal_arithmetic_drem) \ - stub(graal_monitorenter) \ - stub(graal_monitorexit) \ - stub(graal_verify_oop) \ - stub(graal_vm_error) \ - stub(graal_set_deopt_info) \ - stub(graal_create_null_pointer_exception) \ - stub(graal_create_out_of_bounds_exception) \ - stub(graal_log_object) \ - stub(graal_log_printf) \ - stub(graal_log_primitive) \ - stub(graal_identity_hash_code) \ - stub(graal_thread_is_interrupted) \ + stub(register_finalizer) \ + stub(new_instance) \ + stub(new_array) \ + stub(new_multi_array) \ + stub(handle_exception_nofpu) /* optimized version that does not preserve fpu registers */ \ + stub(unwind_exception_call) \ + stub(OSR_migration_end) \ + stub(arithmetic_frem) \ + stub(arithmetic_drem) \ + stub(monitorenter) \ + stub(monitorexit) \ + stub(verify_oop) \ + stub(vm_error) \ + stub(create_null_pointer_exception) \ + stub(create_out_of_bounds_exception) \ + stub(log_object) \ + stub(log_printf) \ + stub(log_primitive) \ + stub(identity_hash_code) \ + stub(thread_is_interrupted) \ last_entry(number_of_ids) #define DECLARE_STUB_ID(x) x ## _id , @@ -140,16 +138,16 @@ static address exception_handler_for_pc(JavaThread* thread); - static void graal_create_null_exception(JavaThread* thread); - static void graal_create_out_of_bounds_exception(JavaThread* thread, jint index); - static void graal_monitorenter(JavaThread* thread, oopDesc* obj, BasicLock* lock); - static void graal_monitorexit (JavaThread* thread, oopDesc* obj, BasicLock* lock); - static void graal_vm_error(JavaThread* thread, oop where, oop format, jlong value); - static void graal_log_printf(JavaThread* thread, oop format, jlong v1, jlong v2, jlong v3); - static void graal_log_primitive(JavaThread* thread, jchar typeChar, jlong value, jboolean newline); + static void create_null_exception(JavaThread* thread); + static void create_out_of_bounds_exception(JavaThread* thread, jint index); + static void monitorenter(JavaThread* thread, oopDesc* obj, BasicLock* lock); + static void monitorexit (JavaThread* thread, oopDesc* obj, BasicLock* lock); + static void vm_error(JavaThread* thread, oop where, oop format, jlong value); + static void log_printf(JavaThread* thread, oop format, jlong v1, jlong v2, jlong v3); + static void log_primitive(JavaThread* thread, jchar typeChar, jlong value, jboolean newline); - static jint graal_identity_hash_code(JavaThread* thread, oopDesc* objd); - static jboolean graal_thread_is_interrupted(JavaThread* thread, oopDesc* obj, jboolean clear_interrupte); + static jint identity_hash_code(JavaThread* thread, oopDesc* objd); + static jboolean thread_is_interrupted(JavaThread* thread, oopDesc* obj, jboolean clear_interrupte); // Note: Must be kept in sync with constants in com.oracle.graal.snippets.Log enum { @@ -157,7 +155,7 @@ LOG_OBJECT_STRING = 0x02, LOG_OBJECT_ADDRESS = 0x04 }; - static void graal_log_object(JavaThread* thread, oop msg, jint flags); + static void log_object(JavaThread* thread, oop msg, jint flags); public: // initialization
--- a/src/share/vm/interpreter/bytecodeInterpreter.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/interpreter/bytecodeInterpreter.cpp Tue Mar 12 11:38:52 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); }
--- a/src/share/vm/interpreter/bytecodeTracer.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/interpreter/bytecodeTracer.cpp Tue Mar 12 11:38:52 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(" <unresolved klass at %d>", i); - } else if (tag.is_object()) { - st->print(" <Object>"); - print_oop(constants->object_at(i), st); } else if (tag.is_method_type()) { int i2 = constants->method_type_index_at(i); st->print(" <MethodType> %d", i2);
--- a/src/share/vm/interpreter/interpreter.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/interpreter/interpreter.cpp Tue Mar 12 11:38:52 2013 +0100 @@ -63,8 +63,9 @@ void InterpreterCodelet::print_on(outputStream* st) const { ttyLocker ttyl; - if (PrintInterpreter || PrintMachineCodeToFile) { + if (PrintInterpreter) { + st->cr(); st->print_cr("----------------------------------------------------------------------"); } @@ -73,7 +74,8 @@ st->print_cr("[" INTPTR_FORMAT ", " INTPTR_FORMAT "] %d bytes", code_begin(), code_end(), code_size()); - if (PrintInterpreter || PrintMachineCodeToFile) { + if (PrintInterpreter) { + st->cr(); Disassembler::decode(code_begin(), code_end(), st, DEBUG_ONLY(_comments) NOT_DEBUG(CodeComments())); } } @@ -388,7 +390,6 @@ assert(method->contains(bcp), "just checkin'"); Bytecodes::Code code = Bytecodes::java_code_at(method, bcp); #if defined(COMPILER1) || defined(GRAAL) - if(code == Bytecodes::_athrow ) { return Interpreter::rethrow_exception_entry(); } @@ -434,8 +435,7 @@ case Bytecodes::_getstatic : case Bytecodes::_putstatic : case Bytecodes::_aastore : -#if defined(COMPILER1) - +#ifdef COMPILER1 //special case of reexecution case Bytecodes::_athrow : #endif
--- a/src/share/vm/interpreter/linkResolver.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/interpreter/linkResolver.cpp Tue Mar 12 11:38:52 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(<resolved_klass>, method_name, method_signature, current_klass, pool, index, CHECK); Symbol* method_name = pool->name_ref_at(index);
--- a/src/share/vm/interpreter/rewriter.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/interpreter/rewriter.cpp Tue Mar 12 11:38:52 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); @@ -116,9 +115,7 @@ while (!bcs.is_last_bytecode()) { Bytecodes::Code opcode = bcs.raw_next(); switch (opcode) { - case Bytecodes::_return: - *bcs.bcp() = Bytecodes::_return_register_finalizer; - break; + case Bytecodes::_return: *bcs.bcp() = Bytecodes::_return_register_finalizer; break; case Bytecodes::_istore: case Bytecodes::_lstore: @@ -240,7 +237,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; @@ -318,12 +315,12 @@ switch (c) { case Bytecodes::_lookupswitch : { #ifndef CC_INTERP - Bytecode_lookupswitch bc(method, bcp); - (*bcp) = ( - bc.number_of_pairs() < BinarySwitchThreshold - ? Bytecodes::_fast_linearswitch - : Bytecodes::_fast_binaryswitch - ); + Bytecode_lookupswitch bc(method, bcp); + (*bcp) = ( + bc.number_of_pairs() < BinarySwitchThreshold + ? Bytecodes::_fast_linearswitch + : Bytecodes::_fast_binaryswitch + ); #endif break; }
--- a/src/share/vm/interpreter/templateInterpreter.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/interpreter/templateInterpreter.cpp Tue Mar 12 11:38:52 2013 +0100 @@ -27,7 +27,6 @@ #include "interpreter/interpreterGenerator.hpp" #include "interpreter/interpreterRuntime.hpp" #include "interpreter/templateTable.hpp" -#include "utilities/machineCodePrinter.hpp" #ifndef CC_INTERP @@ -52,9 +51,6 @@ "Interpreter"); InterpreterGenerator g(_code); if (PrintInterpreter) print(); - if (PrintMachineCodeToFile) { - MachineCodePrinter::print(_code); - } } // initialize dispatch table
--- a/src/share/vm/memory/allocation.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/memory/allocation.hpp Tue Mar 12 11:38:52 2013 +0100 @@ -34,9 +34,6 @@ #ifdef COMPILER2 #include "opto/c2_globals.hpp" #endif -#ifdef GRAAL -#include "graal/graalGlobals.hpp" -#endif #include <new> @@ -148,9 +145,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
--- a/src/share/vm/memory/binaryTreeDictionary.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/memory/binaryTreeDictionary.cpp Tue Mar 12 11:38:52 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 Chunk_t, template <class> class FreeList_t> TreeList<Chunk_t, FreeList_t>* @@ -871,9 +873,9 @@ template <class Chunk_t, template <class> class FreeList_t> void BinaryTreeDictionary<Chunk_t, FreeList_t>::dict_census_update(size_t size, bool split, bool birth){} -#ifndef SERIALGC +#if INCLUDE_ALL_GCS template <> -void BinaryTreeDictionary<FreeChunk, AdaptiveFreeList>::dict_census_update(size_t size, bool split, bool birth){ +void AFLBinaryTreeDictionary::dict_census_update(size_t size, bool split, bool birth){ TreeList<FreeChunk, AdaptiveFreeList>* 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 Chunk_t, template <class> class FreeList_t> bool BinaryTreeDictionary<Chunk_t, FreeList_t>::coal_dict_over_populated(size_t size) { @@ -909,9 +911,9 @@ return true; } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS template <> -bool BinaryTreeDictionary<FreeChunk, AdaptiveFreeList>::coal_dict_over_populated(size_t size) { +bool AFLBinaryTreeDictionary::coal_dict_over_populated(size_t size) { if (FLSAlwaysCoalesceLarge) return true; TreeList<FreeChunk, AdaptiveFreeList>* 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<Chunk_t>* fl) {} -#ifndef SERIALGC +#if INCLUDE_ALL_GCS void do_list(AdaptiveFreeList<Chunk_t>* 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<Chunk_t>* fl) {} -#ifndef SERIALGC +#if INCLUDE_ALL_GCS void do_list(AdaptiveFreeList<Chunk_t>* fl) { double splitSurplusPercent = percentage; fl->set_surplus(fl->count() - (ssize_t)((double)fl->desired() * splitSurplusPercent)); } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS }; template <class Chunk_t, template <class> class FreeList_t> @@ -1157,7 +1159,7 @@ setTreeHintsClosure(size_t v) { hint = v; } void do_list(FreeList<Chunk_t>* fl) {} -#ifndef SERIALGC +#if INCLUDE_ALL_GCS void do_list(AdaptiveFreeList<Chunk_t>* 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 Chunk_t, template <class> class FreeList_t> @@ -1180,7 +1182,7 @@ class clearTreeCensusClosure : public AscendTreeCensusClosure<Chunk_t, FreeList_t> { void do_list(FreeList<Chunk_t>* fl) {} -#ifndef SERIALGC +#if INCLUDE_ALL_GCS void do_list(AdaptiveFreeList<Chunk_t>* 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 Chunk_t, template <class> class FreeList_t> @@ -1252,7 +1254,7 @@ total()->set_count( total()->count() + fl->count() ); } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS void do_list(AdaptiveFreeList<Chunk_t>* fl) { if (++_print_line >= 40) { FreeList_t<Chunk_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 Chunk_t, template <class> class FreeList_t> @@ -1286,9 +1288,9 @@ FreeList_t<Chunk_t>::print_labels_on(gclog_or_tty, " "); } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS template <> -void BinaryTreeDictionary<FreeChunk, AdaptiveFreeList>::print_dict_census(void) const { +void AFLBinaryTreeDictionary::print_dict_census(void) const { gclog_or_tty->print("\nBinaryTree\n"); AdaptiveFreeList<FreeChunk>::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 Chunk_t, template <class> class FreeList_t> class PrintFreeListsClosure : public AscendTreeCensusClosure<Chunk_t, FreeList_t> { @@ -1414,10 +1416,10 @@ template class TreeChunk<Metachunk, FreeList>; -#ifndef SERIALGC +#if INCLUDE_ALL_GCS // Explicitly instantiate these types for FreeChunk. template class TreeList<FreeChunk, AdaptiveFreeList>; template class BinaryTreeDictionary<FreeChunk, AdaptiveFreeList>; template class TreeChunk<FreeChunk, AdaptiveFreeList>; -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS
--- a/src/share/vm/memory/binaryTreeDictionary.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/memory/binaryTreeDictionary.hpp Tue Mar 12 11:38:52 2013 +0100 @@ -43,6 +43,10 @@ template <class Chunk_t, template <class> class FreeList_t> class DescendTreeCensusClosure; template <class Chunk_t, template <class> class FreeList_t> class DescendTreeSearchClosure; +class FreeChunk; +template <class> class AdaptiveFreeList; +typedef BinaryTreeDictionary<FreeChunk, AdaptiveFreeList> AFLBinaryTreeDictionary; + template <class Chunk_t, template <class> class FreeList_t> class TreeList : public FreeList_t<Chunk_t> { friend class TreeChunk<Chunk_t, FreeList_t>;
--- a/src/share/vm/memory/cardTableModRefBS.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/memory/cardTableModRefBS.cpp Tue Mar 12 11:38:52 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
--- a/src/share/vm/memory/cardTableRS.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/memory/cardTableRS.cpp Tue Mar 12 11:38:52 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);
--- a/src/share/vm/memory/collectorPolicy.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/memory/collectorPolicy.cpp Tue Mar 12 11:38:52 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());
--- a/src/share/vm/memory/collectorPolicy.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/memory/collectorPolicy.hpp Tue Mar 12 11:38:52 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 {
--- a/src/share/vm/memory/filemap.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/memory/filemap.cpp Tue Mar 12 11:38:52 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); }
--- a/src/share/vm/memory/freeBlockDictionary.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/memory/freeBlockDictionary.cpp Tue Mar 12 11:38:52 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 <class Chunk> Mutex* FreeBlockDictionary<Chunk>::par_lock() const { @@ -56,7 +58,7 @@ template class FreeBlockDictionary<Metablock>; template class FreeBlockDictionary<Metachunk>; -#ifndef SERIALGC +#if INCLUDE_ALL_GCS // Explicitly instantiate for FreeChunk template class FreeBlockDictionary<FreeChunk>; -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS
--- a/src/share/vm/memory/freeList.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/memory/freeList.cpp Tue Mar 12 11:38:52 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<Metablock>; template class FreeList<Metachunk>; -#ifndef SERIALGC +#if INCLUDE_ALL_GCS template class FreeList<FreeChunk>; -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS
--- a/src/share/vm/memory/genCollectedHeap.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/memory/genCollectedHeap.cpp Tue Mar 12 11:38:52 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 {
--- a/src/share/vm/memory/generationSpec.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/memory/generationSpec.cpp Tue Mar 12 11:38:52 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");
--- a/src/share/vm/memory/heap.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/memory/heap.cpp Tue Mar 12 11:38:52 2013 +0100 @@ -127,7 +127,7 @@ assert(_number_of_reserved_segments >= _number_of_committed_segments, "just checking"); // reserve space for _segmap - if (!_segmap.initialize(align_to_allocation_size(_number_of_reserved_segments), align_to_allocation_size(_number_of_committed_segments))) { + if (!_segmap.initialize(align_to_page_size(_number_of_reserved_segments), align_to_page_size(_number_of_committed_segments))) { return false; }
--- a/src/share/vm/memory/heapInspection.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/memory/heapInspection.cpp Tue Mar 12 11:38:52 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 = "<longArrayKlass>"; else name = "<no 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 <k>, 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<KlassInfoEntry*>(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; c<KlassSizeStats::_num_columns; c++) { + if (selected[c]) {st->print(",%s", name_table[c]);} + } + st->print(",ClassName"); + } else { + st->print("Index Super"); + for (int c=0; c<KlassSizeStats::_num_columns; c++) { + if (selected[c]) {st->print(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; c<KlassSizeStats::_num_columns; c++) { + selected[c] = is_selected(name_table[c]); + } + + for(i=0; i < elements()->length(); 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; c<KlassSizeStats::_num_columns; c++) { + colsum_table[c] += col_table[c]; + } + } else { + int super_index = -1; + if (k->oop_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; c<KlassSizeStats::_num_columns; c++) { + if (selected[c]) {st->print("," JULONG_FORMAT, col_table[c]);} + } + st->print(",%s",e->name()); + } else { + st->print("%5d %5d", e->index(), super_index); + for (int c=0; c<KlassSizeStats::_num_columns; c++) { + if (selected[c]) {print_julong(st, width_table[c], col_table[c]);} + } + st->print(" %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; c<KlassSizeStats::_num_columns; c++) { + width_table[c] = col_width(colsum_table[c], name_table[c]); + } + } + } + + sz_sum._inst_size = 0; + + if (csv_format) { + st->print(","); + for (int c=0; c<KlassSizeStats::_num_columns; c++) { + if (selected[c]) {st->print("," JULONG_FORMAT, colsum_table[c]);} + } + } else { + st->print(" "); + for (int c=0; c<KlassSizeStats::_num_columns; c++) { + if (selected[c]) {print_julong(st, width_table[c], colsum_table[c]);} + } + st->print(" Total"); + if (sz_sum._total_bytes > 0) { + st->cr(); + st->print(" "); + for (int c=0; c<KlassSizeStats::_num_columns; c++) { + if (selected[c]) { + switch (c) { + case KlassSizeStats::_index_inst_size: + case KlassSizeStats::_index_inst_count: + case KlassSizeStats::_index_method_count: + st->print(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<AnnotationArray*>* 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; c<KlassSizeStats::_num_columns; c++) { + st->print("%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"); }
--- a/src/share/vm/memory/heapInspection.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/memory/heapInspection.hpp Tue Mar 12 11:38:52 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 <class T> static int count(T* x) { + return (HeapWordSize * ((x) ? (x)->size() : 0)); + } + + template <class T> 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<mtInternal> { 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<KlassInfoEntry*>* _elements; GrowableArray<KlassInfoEntry*>* 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<AnnotationArray*>* 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 <class T> static int count_bytes(T* x) { + return (HeapWordSize * ((x) ? (x)->size() : 0)); + } + + template <class T> 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<oop>* result) NOT_SERVICES_RETURN; };
--- a/src/share/vm/memory/metaspace.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/memory/metaspace.cpp Tue Mar 12 11:38:52 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); }
--- a/src/share/vm/memory/space.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/memory/space.cpp Tue Mar 12 11:38:52 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;
--- a/src/share/vm/memory/space.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/memory/space.hpp Tue Mar 12 11:38:52 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() {
--- a/src/share/vm/memory/specialized_oop_closures.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/memory/specialized_oop_closures.hpp Tue Mar 12 11:38:52 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) \
--- a/src/share/vm/memory/tenuredGeneration.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/memory/tenuredGeneration.cpp Tue Mar 12 11:38:52 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();
--- a/src/share/vm/memory/tenuredGeneration.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/memory/tenuredGeneration.hpp Tue Mar 12 11:38:52 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();
--- a/src/share/vm/memory/universe.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/memory/universe.cpp Tue Mar 12 11:38:52 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) {
--- a/src/share/vm/memory/universe.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/memory/universe.hpp Tue Mar 12 11:38:52 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().
--- a/src/share/vm/oops/annotations.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/oops/annotations.cpp Tue Mar 12 11:38:52 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<AnnotationArray*>* fa, - Array<AnnotationArray*>* ma, - Array<AnnotationArray*>* mpa, - Array<AnnotationArray*>* mda, TRAPS) { - return new (loader_data, size(), true, THREAD) Annotations(fa, ma, mpa, mda); -} - // helper -static void free_contents(ClassLoaderData* loader_data, Array<AnnotationArray*>* p) { +void Annotations::free_contents(ClassLoaderData* loader_data, Array<AnnotationArray*>* p) { if (p != NULL) { for (int i = 0; i < p->length(); i++) { MetadataFactory::free_array<u1>(loader_data, p->at(i)); @@ -58,44 +51,16 @@ MetadataFactory::free_array<u1>(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<u1>(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<AnnotationArray*>** md_p, - TRAPS) { - Array<AnnotationArray*>* 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<AnnotationArray*>(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<AnnotationArray*>* 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
--- a/src/share/vm/oops/annotations.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/oops/annotations.hpp Tue Mar 12 11:38:52 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<u1> 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<AnnotationArray*>* _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<AnnotationArray*>* _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<AnnotationArray*>* _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<AnnotationArray*>* _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<AnnotationArray*>* fa, Array<AnnotationArray*>* ma, - Array<AnnotationArray*>* mpa, Array<AnnotationArray*>* 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<AnnotationArray*>* _fields_type_annotations; public: // Allocate instance of this class static Annotations* allocate(ClassLoaderData* loader_data, TRAPS); - static Annotations* allocate(ClassLoaderData* loader_data, - Array<AnnotationArray*>* fa, - Array<AnnotationArray*>* ma, - Array<AnnotationArray*>* mpa, - Array<AnnotationArray*>* mda, TRAPS); + + static void free_contents(ClassLoaderData* loader_data, Array<AnnotationArray*>* 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<AnnotationArray*>* fields_annotations() const { return _fields_annotations; } - Array<AnnotationArray*>* methods_annotations() const { return _methods_annotations; } - Array<AnnotationArray*>* methods_parameter_annotations() const { return _methods_parameter_annotations; } - Array<AnnotationArray*>* 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<AnnotationArray*>* fields_type_annotations() const { return _fields_type_annotations; } void set_class_annotations(AnnotationArray* md) { _class_annotations = md; } void set_fields_annotations(Array<AnnotationArray*>* md) { _fields_annotations = md; } - void set_methods_annotations(Array<AnnotationArray*>* md) { _methods_annotations = md; } - void set_methods_parameter_annotations(Array<AnnotationArray*>* md) { _methods_parameter_annotations = md; } - void set_methods_default_annotations(Array<AnnotationArray*>* 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<AnnotationArray*>* 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<AnnotationArray*>* annos); - void set_annotations(Array<AnnotationArray*>* md, Array<AnnotationArray*>** md_p) { *md_p = md; } - bool is_klass() const { return false; } private: - void set_methods_annotations_of(instanceKlassHandle ik, - int idnum, AnnotationArray* anno, - Array<AnnotationArray*>** md_p, TRAPS); - + static julong count_bytes(Array<AnnotationArray*>* 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<AnnotationArray*>* annos) { - if (annos == NULL || annos->length() <= idnum) { - return NULL; - } - return annos->at(idnum); -} #endif // SHARE_VM_OOPS_ANNOTATIONS_HPP
--- a/src/share/vm/oops/arrayKlass.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/oops/arrayKlass.hpp Tue Mar 12 11:38:52 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; }
--- a/src/share/vm/oops/constMethod.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/oops/constMethod.cpp Tue Mar 12 11:38:52 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<u1>(loader_data, stackmap_data()); } set_stackmap_data(NULL); + + // deallocate annotation arrays + if (has_method_annotations()) + MetadataFactory::free_array<u1>(loader_data, method_annotations()); + if (has_parameter_annotations()) + MetadataFactory::free_array<u1>(loader_data, parameter_annotations()); + if (has_type_annotations()) + MetadataFactory::free_array<u1>(loader_data, type_annotations()); + if (has_default_annotations()) + MetadataFactory::free_array<u1>(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;
--- a/src/share/vm/oops/constMethod.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/oops/constMethod.hpp Tue Mar 12 11:38:52 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<u1> 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<u1>* _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
--- a/src/share/vm/oops/constantPool.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/oops/constantPool.cpp Tue Mar 12 11:38:52 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
--- a/src/share/vm/oops/constantPool.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/oops/constantPool.hpp Tue Mar 12 11:38:52 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<u2>* _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<u2>* 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<u1>* tags() const { return _tags; } Array<u2>* 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; }
--- a/src/share/vm/oops/cpCache.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/oops/cpCache.cpp Tue Mar 12 11:38:52 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
--- a/src/share/vm/oops/cpCache.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/oops/cpCache.hpp Tue Mar 12 11:38:52 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; })
--- a/src/share/vm/oops/generateOopMap.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/oops/generateOopMap.cpp Tue Mar 12 11:38:52 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");
--- a/src/share/vm/oops/instanceClassLoaderKlass.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/oops/instanceClassLoaderKlass.cpp Tue Mar 12 11:38:52 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
--- a/src/share/vm/oops/instanceClassLoaderKlass.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/oops/instanceClassLoaderKlass.hpp Tue Mar 12 11:38:52 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);
--- a/src/share/vm/oops/instanceKlass.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/oops/instanceKlass.cpp Tue Mar 12 11:38:52 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<Method*>* 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 {
--- a/src/share/vm/oops/instanceKlass.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/oops/instanceKlass.hpp Tue Mar 12 11:38:52 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<u2>* _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<AnnotationArray*>* 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<AnnotationArray*>* 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: @@ -1015,6 +1024,7 @@ void print_value_on(outputStream* st) const; void oop_print_value_on(oop obj, outputStream* st); + #ifndef PRODUCT void oop_print_on (oop obj, outputStream* st);
--- a/src/share/vm/oops/instanceMirrorKlass.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/oops/instanceMirrorKlass.cpp Tue Mar 12 11:38:52 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()) {
--- a/src/share/vm/oops/instanceMirrorKlass.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/oops/instanceMirrorKlass.hpp Tue Mar 12 11:38:52 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
--- a/src/share/vm/oops/instanceRefKlass.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/oops/instanceRefKlass.cpp Tue Mar 12 11:38:52 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 <class T> void specialized_oop_follow_contents(InstanceRefKlass* ref, oop obj) { @@ -120,7 +121,7 @@ } } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS template <class T> void specialized_oop_follow_contents(InstanceRefKlass* ref, ParCompactionManager* cm, @@ -194,7 +195,7 @@ specialized_oop_follow_contents<oop>(this, cm, obj); } } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS #ifdef ASSERT template <class T> 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 <class T> 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
--- a/src/share/vm/oops/instanceRefKlass.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/oops/instanceRefKlass.hpp Tue Mar 12 11:38:52 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);
--- a/src/share/vm/oops/klass.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/oops/klass.cpp Tue Mar 12 11:38:52 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
--- a/src/share/vm/oops/klass.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/oops/klass.hpp Tue Mar 12 11:38:52 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));
--- a/src/share/vm/oops/klassPS.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/oops/klassPS.hpp Tue Mar 12 11:38:52 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
--- a/src/share/vm/oops/klassVtable.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/oops/klassVtable.cpp Tue Mar 12 11:38:52 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
--- a/src/share/vm/oops/klassVtable.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/oops/klassVtable.hpp Tue Mar 12 11:38:52 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<Method*>* methods, AccessFlags class_flags, Handle classloader, Symbol* classname, Array<Klass*>* 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<Klass*>* 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
--- a/src/share/vm/oops/method.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/oops/method.cpp Tue Mar 12 11:38:52 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" @@ -53,9 +54,6 @@ #include "runtime/signature.hpp" #include "utilities/quickSort.hpp" #include "utilities/xmlstream.hpp" -#ifdef GRAAL -#include "graal/graalJavaAccess.hpp" -#endif // Implementation of Method @@ -63,24 +61,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 +312,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 +319,6 @@ void Method::remove_unshareable_info() { unlink_method(); - set_interpreter_kind(); } @@ -707,7 +686,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,15 +700,21 @@ } 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)) { - ResourceMark rm; 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 +736,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 +762,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 +1021,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 +1031,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 +1082,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 +1310,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<Method*>* methods, - Array<AnnotationArray*>* annotations, - GrowableArray<AnnotationArray*>* 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 +1317,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<Method*>* methods, - Array<AnnotationArray*>* methods_annotations, - Array<AnnotationArray*>* methods_parameter_annotations, - Array<AnnotationArray*>* methods_default_annotations, - Array<AnnotationArray*>* methods_type_annotations, - bool idempotent) { +void Method::sort_methods(Array<Method*>* 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<Method*>(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<AnnotationArray*>* temp_array = new GrowableArray<AnnotationArray*>(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 +1334,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 +1371,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 +1908,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 @@ -1979,16 +1940,3 @@ guarantee(md == NULL || md->is_methodData(), "should be method data"); } - -#ifdef GRAAL -void DebugScopedMethod::print_on(outputStream* st) { - if (_method != NULL) { - st->print("Method@%p", _method); - char holder[O_BUFLEN]; - char nameAndSig[O_BUFLEN]; - _method->method_holder()->name()->as_C_string(holder, O_BUFLEN); - _method->name_and_sig_as_C_string(nameAndSig, O_BUFLEN); - st->print(" - %s::%s", holder, nameAndSig); - } -} -#endif
--- a/src/share/vm/oops/method.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/oops/method.hpp Tue Mar 12 11:38:52 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<Method*>* methods, - Array<AnnotationArray*>* methods_annotations, - Array<AnnotationArray*>* methods_parameter_annotations, - Array<AnnotationArray*>* methods_default_annotations, - Array<AnnotationArray*>* methods_type_annotations, - bool idempotent = false); + static void sort_methods(Array<Method*>* methods, bool idempotent = false); // Deallocation function for redefine classes or if an error occurs void deallocate_contents(ClassLoaderData* loader_data); @@ -1022,20 +1000,4 @@ } }; -#ifdef GRAAL -class DebugScopedMethod : public DebugScopedValue { -private: - Method* _method; -public: - DebugScopedMethod(const char* file, int line, Method* method) : DebugScopedValue(file, line), _method(method) {} - void print_on(outputStream* st); -}; -#define DS_METHOD(method) DebugScopedMethod __dsm__(__FILE__, __LINE__, method) -#define DS_METHOD1(var, method) DebugScopedMethod var(__FILE__, __LINE__, method) -#else -#define DS_METHOD(method) do {} while (0) -#define DS_METHOD1(var, method) do {} while (0) -#endif - #endif // SHARE_VM_OOPS_METHODOOP_HPP -
--- a/src/share/vm/oops/methodData.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/oops/methodData.cpp Tue Mar 12 11:38:52 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" @@ -759,13 +760,6 @@ return CompilationPolicy::policy()->is_mature(_method); } -void MethodData::inc_decompile_count() { - _nof_decompiles += 1; - if (decompile_count() > (uint)PerMethodRecompilationCutoff) { - method()->set_not_compilable(CompLevel_full_optimization); - } -} - // Translate a bci to its corresponding data index (di). address MethodData::bci_to_dp(int bci) { ResourceMark rm; @@ -890,6 +884,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
--- a/src/share/vm/oops/methodData.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/oops/methodData.hpp Tue Mar 12 11:38:52 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() {
--- a/src/share/vm/oops/objArrayKlass.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/oops/objArrayKlass.cpp Tue Mar 12 11:38:52 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<oop>(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
--- a/src/share/vm/oops/objArrayKlass.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/oops/objArrayKlass.hpp Tue Mar 12 11:38:52 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 <class T> 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) {
--- a/src/share/vm/oops/objArrayKlass.inline.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/oops/objArrayKlass.inline.hpp Tue Mar 12 11:38:52 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
--- a/src/share/vm/oops/oop.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/oops/oop.hpp Tue Mar 12 11:38:52 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);
--- a/src/share/vm/oops/oop.inline.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/oops/oop.inline.hpp Tue Mar 12 11:38:52 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
--- a/src/share/vm/oops/oop.pcgc.inline.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/oops/oop.pcgc.inline.hpp Tue Mar 12 11:38:52 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
--- a/src/share/vm/oops/oop.psgc.inline.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/oops/oop.psgc.inline.hpp Tue Mar 12 11:38:52 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
--- a/src/share/vm/oops/symbol.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/oops/symbol.cpp Tue Mar 12 11:38:52 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()); }
--- a/src/share/vm/oops/typeArrayKlass.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/oops/typeArrayKlass.cpp Tue Mar 12 11:38:52 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
--- a/src/share/vm/opto/bytecodeInfo.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/opto/bytecodeInfo.cpp Tue Mar 12 11:38:52 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,23 +217,27 @@ // %%% 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"; + set_msg("disallowed by CompilerOracle"); + return false; } // Now perform checks which are heuristic @@ -223,7 +245,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 +257,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 +279,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 +304,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 +351,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 +366,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 +388,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 +411,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 +468,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 +504,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 +557,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 +570,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; }
--- a/src/share/vm/opto/c2_globals.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/opto/c2_globals.hpp Tue Mar 12 11:38:52 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)
--- a/src/share/vm/opto/callGenerator.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/opto/callGenerator.cpp Tue Mar 12 11:38:52 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; }
--- a/src/share/vm/opto/compile.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/opto/compile.cpp Tue Mar 12 11:38:52 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<Node*>(comp_arena(), 8, 0, NULL); _predicate_opaqs = new(comp_arena()) GrowableArray<Node*>(comp_arena(), 8, 0, NULL); + _expensive_nodes = new(comp_arena()) GrowableArray<Node*>(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); + } +}
--- a/src/share/vm/opto/compile.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/opto/compile.hpp Tue Mar 12 11:38:52 2013 +0100 @@ -314,6 +314,7 @@ GrowableArray<CallGenerator*>* _intrinsics; // List of intrinsics. GrowableArray<Node*>* _macro_nodes; // List of nodes which need to be expanded before matching. GrowableArray<Node*>* _predicate_opaqs; // List of Opaque1 nodes for the loop predicates. + GrowableArray<Node*>* _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<PrintInliningBuffer>* _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; }
--- a/src/share/vm/opto/generateOptoStub.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/opto/generateOptoStub.cpp Tue Mar 12 11:38:52 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);
--- a/src/share/vm/opto/library_call.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/opto/library_call.cpp Tue Mar 12 11:38:52 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)
--- a/src/share/vm/opto/loopnode.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/opto/loopnode.cpp Tue Mar 12 11:38:52 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() &&
--- a/src/share/vm/opto/loopnode.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/opto/loopnode.hpp Tue Mar 12 11:38:52 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
--- a/src/share/vm/opto/memnode.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/opto/memnode.cpp Tue Mar 12 11:38:52 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();
--- a/src/share/vm/opto/memnode.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/opto/memnode.hpp Tue Mar 12 11:38:52 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)
--- a/src/share/vm/opto/node.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/opto/node.cpp Tue Mar 12 11:38:52 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
--- a/src/share/vm/opto/node.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/opto/node.hpp Tue Mar 12 11:38:52 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
--- a/src/share/vm/opto/parse.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/opto/parse.hpp Tue Mar 12 11:38:52 2013 +0100 @@ -58,7 +58,7 @@ GrowableArray<InlineTree*> _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);
--- a/src/share/vm/opto/parse3.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/opto/parse3.cpp Tue Mar 12 11:38:52 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;
--- a/src/share/vm/opto/phaseX.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/opto/phaseX.cpp Tue Mar 12 11:38:52 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;
--- a/src/share/vm/opto/regmask.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/opto/regmask.cpp Tue Mar 12 11:38:52 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 } } }
--- a/src/share/vm/opto/regmask.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/opto/regmask.hpp Tue Mar 12 11:38:52 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);
--- a/src/share/vm/opto/subnode.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/opto/subnode.hpp Tue Mar 12 11:38:52 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; }
--- a/src/share/vm/opto/superword.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/opto/superword.cpp Tue Mar 12 11:38:52 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---------------------------
--- a/src/share/vm/opto/superword.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/opto/superword.hpp Tue Mar 12 11:38:52 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
--- a/src/share/vm/precompiled/precompiled.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/precompiled/precompiled.hpp Tue Mar 12 11:38:52 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
--- a/src/share/vm/prims/jni.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/prims/jni.cpp Tue Mar 12 11:38:52 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" @@ -1318,7 +1319,6 @@ } -static bool first_time_InvokeMain = true; static void jni_invoke_static(JNIEnv *env, JavaValue* result, jobject receiver, JNICallType call_type, jmethodID method_id, JNI_ArgumentPusher *args, TRAPS) { methodHandle method(THREAD, Method::resolve_jmethod_id(method_id)); @@ -1327,8 +1327,6 @@ // the jni parser ResourceMark rm(THREAD); int number_of_parameters = method->size_of_parameters(); - - // Invoke the method. Result is returned as oop. JavaCallArguments java_args(number_of_parameters); args->set_java_argument_object(&java_args); @@ -1336,23 +1334,16 @@ // Fill out JavaCallArguments object args->iterate( Fingerprinter(method).fingerprint() ); - // Initialize result type (must be done after args->iterate()) + // Initialize result type result->set_type(args->get_ret_type()); + // Invoke the method. Result is returned as oop. JavaCalls::call(result, method, &java_args, CHECK); // Convert result if (result->get_type() == T_OBJECT || result->get_type() == T_ARRAY) { result->set_jobject(JNIHandles::make_local(env, (oop) result->get_jobject())); } - -#ifdef HIGH_LEVEL_INTERPRETER - if (invoked_main_method) { - assert(THREAD->is_Java_thread(), "other threads must not call into java"); - JavaThread* thread = (JavaThread*)THREAD; - thread->set_high_level_interpreter_in_vm(false); - } -#endif } @@ -2654,7 +2645,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 +2664,7 @@ G1SATBCardTableModRefBS::enqueue(referent); } } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS #ifndef USDT2 DTRACE_PROBE1(hotspot_jni, GetObjectField__return, ret); #else /* USDT2 */
--- a/src/share/vm/prims/jniCheck.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/prims/jniCheck.hpp Tue Mar 12 11:38:52 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.
--- a/src/share/vm/prims/jvm.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/prims/jvm.cpp Tue Mar 12 11:38:52 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
--- a/src/share/vm/prims/jvm.h Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/prims/jvm.h Tue Mar 12 11:38:52 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;
--- a/src/share/vm/prims/jvmtiCodeBlobEvents.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/prims/jvmtiCodeBlobEvents.hpp Tue Mar 12 11:38:52 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;
--- a/src/share/vm/prims/jvmtiEnv.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/prims/jvmtiEnv.cpp Tue Mar 12 11:38:52 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
--- a/src/share/vm/prims/jvmtiEnvBase.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/prims/jvmtiEnvBase.cpp Tue Mar 12 11:38:52 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
--- a/src/share/vm/prims/jvmtiEnvBase.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/prims/jvmtiEnvBase.hpp Tue Mar 12 11:38:52 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
--- a/src/share/vm/prims/jvmtiExport.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/prims/jvmtiExport.cpp Tue Mar 12 11:38:52 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
--- a/src/share/vm/prims/jvmtiExport.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/prims/jvmtiExport.hpp Tue Mar 12 11:38:52 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"
--- a/src/share/vm/prims/jvmtiExtensions.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/prims/jvmtiExtensions.hpp Tue Mar 12 11:38:52 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 //
--- a/src/share/vm/prims/jvmtiImpl.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/prims/jvmtiImpl.cpp Tue Mar 12 11:38:52 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
--- a/src/share/vm/prims/jvmtiImpl.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/prims/jvmtiImpl.hpp Tue Mar 12 11:38:52 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
--- a/src/share/vm/prims/jvmtiRawMonitor.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/prims/jvmtiRawMonitor.hpp Tue Mar 12 11:38:52 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
--- a/src/share/vm/prims/jvmtiRedefineClasses.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/prims/jvmtiRedefineClasses.cpp Tue Mar 12 11:38:52 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<Metadata*>* _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<Metadata*>(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<AnnotationArray*>* fields_annotations = sca->fields_annotations(); + Array<AnnotationArray*>* 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<AnnotationArray*>* 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<AnnotationArray*>* 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<AnnotationArray*>* 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<u1>(loader_data, new_class_type_annotations); + scratch_class->annotations()->set_class_type_annotations(NULL); + } + Array<AnnotationArray*>* 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
--- a/src/share/vm/prims/jvmtiRedefineClasses.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/prims/jvmtiRedefineClasses.hpp Tue Mar 12 11:38:52 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
--- a/src/share/vm/prims/jvmtiRedefineClassesTrace.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/prims/jvmtiRedefineClassesTrace.hpp Tue Mar 12 11:38:52 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); \
--- a/src/share/vm/prims/jvmtiTagMap.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/prims/jvmtiTagMap.cpp Tue Mar 12 11:38:52 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 //
--- a/src/share/vm/prims/jvmtiTagMap.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/prims/jvmtiTagMap.hpp Tue Mar 12 11:38:52 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;
--- a/src/share/vm/prims/nativeLookup.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/prims/nativeLookup.cpp Tue Mar 12 11:38:52 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
--- a/src/share/vm/prims/unsafe.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/prims/unsafe.cpp Tue Mar 12 11:38:52 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
--- a/src/share/vm/prims/wbtestmethods/parserTests.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/prims/wbtestmethods/parserTests.hpp Tue Mar 12 11:38:52 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
--- a/src/share/vm/prims/whitebox.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/prims/whitebox.cpp Tue Mar 12 11:38:52 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
--- a/src/share/vm/prims/whitebox.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/prims/whitebox.hpp Tue Mar 12 11:38:52 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:
--- a/src/share/vm/runtime/arguments.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/runtime/arguments.cpp Tue Mar 12 11:38:52 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" @@ -104,9 +105,6 @@ SystemProperty *Arguments::_java_home = NULL; SystemProperty *Arguments::_java_class_path = NULL; SystemProperty *Arguments::_sun_boot_class_path = NULL; -#ifdef GRAAL -SystemProperty *Arguments::_compiler_class_path = NULL; -#endif char* Arguments::_meta_index_path = NULL; char* Arguments::_meta_index_dir = NULL; @@ -168,9 +166,6 @@ _java_library_path = new SystemProperty("java.library.path", NULL, true); _java_home = new SystemProperty("java.home", NULL, true); _sun_boot_class_path = new SystemProperty("sun.boot.class.path", NULL, true); -#ifdef GRAAL - _compiler_class_path = new SystemProperty("compiler.class.path", NULL, true); -#endif _java_class_path = new SystemProperty("java.class.path", "", true); @@ -182,9 +177,6 @@ PropertyList_add(&_system_properties, _java_home); PropertyList_add(&_system_properties, _java_class_path); PropertyList_add(&_system_properties, _sun_boot_class_path); -#ifdef GRAAL - PropertyList_add(&_system_properties, _compiler_class_path); -#endif // Set OS specific system properties values os::init_system_properties_values(); @@ -845,7 +837,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 +849,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 +1095,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 +1266,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 +1311,7 @@ tty->print_cr("ConcGCThreads: %u", ConcGCThreads); } } -#endif // INCLUDE_ALTERNATE_GCS +#endif // INCLUDE_ALL_GCS void set_object_alignment() { // Object alignment. @@ -1319,10 +1328,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 +1456,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 +1747,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 +1896,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 +1921,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 +2016,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 +2025,7 @@ status = status && verify_min_value((intx)G1ConcMarkStepDurationMillis, 1, "G1ConcMarkStepDurationMillis"); } -#endif +#endif // INCLUDE_ALL_GCS status = status && verify_interval(RefDiscoveryPolicy, ReferenceProcessor::DiscoveryPolicyMin, @@ -2158,58 +2180,6 @@ } // Parse JavaVMInitArgs structure -#ifdef GRAAL -static void prepend_to_graal_classpath(SysClassPath &cp, const char* path) { - cp.add_prefix(path); -} - -static void prepend_to_graal_classpath(SysClassPath &cp, const char* graal_dir, const char* project) { - const int BUFFER_SIZE = 1024; - char path[BUFFER_SIZE]; - - const char fileSep = *os::file_separator(); - sprintf(path, "%s%c%s%cbin", graal_dir, fileSep, project, fileSep); - - DIR* dir = os::opendir(path); - if (dir == NULL) { - jio_fprintf(defaultStream::output_stream(), "Error while starting Graal VM: The Graal class directory %s could not be opened.\n", path); - vm_exit(1); - } - os::closedir(dir); - prepend_to_graal_classpath(cp, path); -} - -// Walk up the directory hierarchy starting from JAVA_HOME looking -// for a directory named "graal". If found, then the full path to -// this directory is returned in graal_dir. -static bool find_graal_dir(char* graal_dir) { - strcpy(graal_dir, Arguments::get_java_home()); - char* end = graal_dir + strlen(graal_dir); - const char fileSep = *os::file_separator(); - while (end != graal_dir) { - if (fileSep == '/') - strcat(graal_dir, "/graal"); - else { - assert(fileSep == '\\', "unexpected separator char"); - strcat(graal_dir, "\\graal"); - } - DIR* dir = os::opendir(graal_dir); - if (dir != NULL) { - os::closedir(dir); - return true; - } - *end = 0; - while (end != graal_dir) { - if (*end == fileSep) { - *end = 0; - break; - } - end--; - } - } - return false; -} -#endif jint Arguments::parse_vm_init_args(const JavaVMInitArgs* args) { // For components of the system classpath. @@ -2237,72 +2207,6 @@ return result; } -#ifdef GRAAL - if (PrintVMOptions) { - tty->print_cr("Running Graal VM... "); - } - - SysClassPath scp_compiler(""); - - if (GraalClassPath != NULL) { - prepend_to_graal_classpath(scp_compiler, GraalClassPath); - } else { - const int BUFFER_SIZE = 1024; - char graal_dir[BUFFER_SIZE]; - if (!os::getenv("GRAAL", graal_dir, sizeof(graal_dir))) { - if (find_graal_dir(graal_dir) == false) { - jio_fprintf(defaultStream::output_stream(), "Error while starting Graal VM: The GRAAL environment variable needs to point to the directory containing the Graal projects.\n"); - vm_exit(0); - } - } - if (PrintVMOptions) tty->print_cr("GRAAL=%s", graal_dir); - - // this declaration is checked for correctness by 'mx build' - only - // modify its entries, not its name or shape - const char* graal_projects[] = { - #ifdef AMD64 - "com.oracle.graal.amd64", - "com.oracle.graal.asm.amd64", - "com.oracle.graal.lir.amd64", - "com.oracle.graal.compiler.amd64", - "com.oracle.graal.hotspot.amd64", - #endif - "com.oracle.graal.api.runtime", - "com.oracle.graal.api.meta", - "com.oracle.graal.api.code", - "com.oracle.graal.hotspot", - "com.oracle.graal.asm", - "com.oracle.graal.alloc", - "com.oracle.graal.word", - "com.oracle.graal.snippets", - "com.oracle.graal.compiler", - "com.oracle.graal.loop", - "com.oracle.graal.phases", - "com.oracle.graal.phases.common", - "com.oracle.graal.virtual", - "com.oracle.graal.nodes", - "com.oracle.graal.printer", - "com.oracle.graal.debug", - "com.oracle.graal.graph", - "com.oracle.graal.lir", - "com.oracle.graal.bytecode", - "com.oracle.graal.java" - }; - - const int len = sizeof(graal_projects) / sizeof(char*); - for (int i = 0; i < len; i++) { - if (PrintVMOptions) { - tty->print_cr("Adding project directory %s to bootclasspath", graal_projects[i]); - } - prepend_to_graal_classpath(scp_compiler, graal_dir, graal_projects[i]); - } - } - - scp_compiler.expand_endorsed(); - Arguments::set_compilerclasspath(scp_compiler.combined_path()); - -#endif - if (AggressiveOpts) { // Insert alt-rt.jar between user-specified bootclasspath // prefix and the default bootclasspath. os::set_boot_path() @@ -2318,19 +2222,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 +2516,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 +2536,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 +2867,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 +3111,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 +3247,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 +3302,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 +3332,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 +3344,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 +3443,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 +3454,7 @@ UseNUMAInterleaving = true; } } -#endif +#endif // INCLUDE_ALL_GCS return JNI_OK; } @@ -3645,36 +3549,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.
--- a/src/share/vm/runtime/arguments.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/runtime/arguments.hpp Tue Mar 12 11:38:52 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 @@ -247,9 +247,6 @@ static SystemProperty *_java_home; static SystemProperty *_java_class_path; static SystemProperty *_sun_boot_class_path; -#ifdef GRAAL - static SystemProperty *_compiler_class_path; -#endif // Meta-index for knowing what packages are in the boot class path static char* _meta_index_path; @@ -537,9 +534,6 @@ static void set_ext_dirs(char *value) { _java_ext_dirs->set_value(value); } static void set_endorsed_dirs(char *value) { _java_endorsed_dirs->set_value(value); } static void set_sysclasspath(char *value) { _sun_boot_class_path->set_value(value); } -#ifdef GRAAL - static void set_compilerclasspath(char *value) { _compiler_class_path->set_value(value); } -#endif static void append_sysclasspath(const char *value) { _sun_boot_class_path->append_value(value); } static void set_meta_index_path(char* meta_index_path, char* meta_index_dir) { _meta_index_path = meta_index_path; @@ -550,9 +544,6 @@ static char *get_dll_dir() { return _sun_boot_library_path->value(); } static char *get_endorsed_dir() { return _java_endorsed_dirs->value(); } static char *get_sysclasspath() { return _sun_boot_class_path->value(); } -#ifdef GRAAL - static char *get_compilerclasspath() { return _compiler_class_path->value(); } -#endif static char* get_meta_index_path() { return _meta_index_path; } static char* get_meta_index_dir() { return _meta_index_dir; } @@ -561,11 +552,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
--- a/src/share/vm/runtime/atomic.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/runtime/atomic.hpp Tue Mar 12 11:38:52 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,
--- a/src/share/vm/runtime/basicLock.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/runtime/basicLock.hpp Tue Mar 12 11:38:52 2013 +0100 @@ -63,7 +63,6 @@ public: // Manipulation oop obj() const { return _obj; } - oop* obj_addr() { return &_obj; } void set_obj(oop obj) { _obj = obj; } BasicLock* lock() { return &_lock; }
--- a/src/share/vm/runtime/compilationPolicy.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/runtime/compilationPolicy.cpp Tue Mar 12 11:38:52 2013 +0100 @@ -60,7 +60,7 @@ break; case 1: -#if defined(COMPILER2) +#ifdef COMPILER2 CompilationPolicy::set_policy(new StackWalkCompPolicy()); #else Unimplemented(); @@ -81,7 +81,7 @@ #endif break; case 4: -#if defined(GRAALVM) +#ifdef GRAALVM CompilationPolicy::set_policy(new GraalCompPolicy()); #else Unimplemented(); @@ -188,7 +188,6 @@ #endif #ifdef COMPILER1 - GRAALVM_ONLY(ShouldNotReachHere();) if (is_c1_compile(comp_level)) { return _compiler_count; } else { @@ -212,7 +211,6 @@ } void NonTieredCompPolicy::reset_counter_for_back_branch_event(methodHandle m) { -// GRAAL_ONLY(assert(false, "unexpected")); // Delay next back-branch event but pump up invocation counter to triger // whole method compilation. InvocationCounter* i = m->invocation_counter(); @@ -510,7 +508,7 @@ // StackWalkCompPolicy - walk up stack to find a suitable method to compile -#if defined(COMPILER2) +#ifdef COMPILER2 const char* StackWalkCompPolicy::_msg = NULL;
--- a/src/share/vm/runtime/compilationPolicy.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/runtime/compilationPolicy.hpp Tue Mar 12 11:38:52 2013 +0100 @@ -126,7 +126,7 @@ // StackWalkCompPolicy - existing C2 policy -#if defined(COMPILER2) +#ifdef COMPILER2 class StackWalkCompPolicy : public NonTieredCompPolicy { public: virtual void method_invocation_event(methodHandle m, JavaThread* thread);
--- a/src/share/vm/runtime/deoptimization.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/runtime/deoptimization.cpp Tue Mar 12 11:38:52 2013 +0100 @@ -1312,20 +1312,6 @@ if (TraceDeoptimization) { tty->print_cr(" bci=%d pc=%d, relative_pc=%d, method=%s", trap_scope->bci(), fr.pc(), fr.pc() - nm->code_begin(), trap_scope->method()->name()->as_C_string()); -#ifdef GRAAL - if (thread->graal_deopt_info() != NULL) { - oop deopt_info = thread->graal_deopt_info(); - if (java_lang_String::is_instance(deopt_info)) { - char buf[O_BUFLEN]; - java_lang_String::as_utf8_string(deopt_info, buf, O_BUFLEN); - tty->print_cr("deopt info: %s", buf); - } else { - tty->print_cr("deopt info:"); - deopt_info->print(); - } - thread->set_graal_deopt_info(NULL); - } -#endif } methodHandle trap_method = trap_scope->method(); @@ -1339,7 +1325,7 @@ GrowableArray<ScopeValue*>* expressions = trap_scope->expressions(); guarantee(expressions != NULL, "must have exception to throw"); ScopeValue* topOfStack = expressions->top(); - Handle topOfStackObj = cvf->create_stack_value(topOfStack)->get_obj(); + Handle topOfStackObj = StackValue::create_stack_value(&fr, ®_map, topOfStack)->get_obj(); THREAD->set_pending_exception(topOfStackObj(), NULL, 0); } @@ -1637,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(). } }
--- a/src/share/vm/runtime/deoptimization.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/runtime/deoptimization.hpp Tue Mar 12 11:38:52 2013 +0100 @@ -37,7 +37,7 @@ friend class VMStructs; public: - // What condition caused the deoptimization + // What condition caused the deoptimization? enum DeoptReason { Reason_many = -1, // indicates presence of several reasons Reason_none = 0, // indicates absence of a relevant deopt. @@ -85,7 +85,7 @@ // Note: Reason_RECORDED_LIMIT should be < 8 to fit into 3 bits of // DataLayout::trap_bits. This dependency is enforced indirectly // via asserts, to avoid excessive direct header-to-header dependencies. - // See Deoptimization::trap_state_reason and class DataLayout + // See Deoptimization::trap_state_reason and class DataLayout. }; // What action must be taken by the runtime? @@ -132,7 +132,7 @@ // executing in a particular CodeBlob if UseBiasedLocking is enabled static void revoke_biases_of_monitors(CodeBlob* cb); -//#ifdef COMPILER2 +#if defined(COMPILER2) || defined(GRAAL) // Support for restoring non-escaping objects static bool realloc_objects(JavaThread* thread, frame* fr, GrowableArray<ScopeValue*>* objects, TRAPS); static void reassign_type_array_elements(frame* fr, RegisterMap* reg_map, ObjectValue* sv, typeArrayOop obj, BasicType type); @@ -140,7 +140,7 @@ static void reassign_fields(frame* fr, RegisterMap* reg_map, GrowableArray<ScopeValue*>* objects); static void relock_objects(GrowableArray<MonitorInfo*>* monitors, JavaThread* thread); NOT_PRODUCT(static void print_objects(GrowableArray<ScopeValue*>* objects);) -//#endif // COMPILER2 +#endif // COMPILER2 || GRAAL public: static vframeArray* create_vframeArray(JavaThread* thread, frame fr, RegisterMap *reg_map, GrowableArray<compiledVFrame*>* chunk); @@ -319,12 +319,11 @@ assert((1 << _reason_bits) >= Reason_LIMIT, "enough bits"); assert((1 << _action_bits) >= Action_LIMIT, "enough bits"); int trap_request; - if (index != -1) { + if (index != -1) trap_request = index; - } else { + else trap_request = (~(((reason) << _reason_shift) + ((action) << _action_shift))); - } assert(reason == trap_request_reason(trap_request), "valid reason"); assert(action == trap_request_action(trap_request), "valid action"); assert(index == trap_request_index(trap_request), "valid index");
--- a/src/share/vm/runtime/fieldDescriptor.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/runtime/fieldDescriptor.cpp Tue Mar 12 11:38:52 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<AnnotationArray*>* type_annos = ik->fields_type_annotations(); if (type_annos == NULL) return NULL; - Array<AnnotationArray*>* 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 {
--- a/src/share/vm/runtime/fieldDescriptor.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/runtime/fieldDescriptor.hpp Tue Mar 12 11:38:52 2013 +0100 @@ -25,10 +25,7 @@ #ifndef SHARE_VM_RUNTIME_FIELDDESCRIPTOR_HPP #define SHARE_VM_RUNTIME_FIELDDESCRIPTOR_HPP -#include "oops/annotations.hpp" #include "oops/constantPool.hpp" -#include "oops/fieldInfo.hpp" -#include "oops/instanceKlass.hpp" #include "oops/symbol.hpp" #include "runtime/fieldType.hpp" #include "utilities/accessFlags.hpp"
--- a/src/share/vm/runtime/fprofiler.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/runtime/fprofiler.hpp Tue Mar 12 11:38:52 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
--- a/src/share/vm/runtime/frame.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/runtime/frame.cpp Tue Mar 12 11:38:52 2013 +0100 @@ -597,67 +597,44 @@ void frame::interpreter_frame_print_on(outputStream* st) const { #ifndef PRODUCT assert(is_interpreted_frame(), "Not an interpreted frame"); - assert(interpreter_frame_method() != NULL && interpreter_frame_method()->contains(interpreter_frame_bcp()), "must be"); jint i; - st->print_cr(" - sp = " INTPTR_FORMAT, sp()); - // expressions + for (i = 0; i < interpreter_frame_method()->max_locals(); i++ ) { + intptr_t x = *interpreter_frame_local_at(i); + st->print(" - local [" INTPTR_FORMAT "]", x); + st->fill_to(23); + st->print_cr("; #%d", i); + } for (i = interpreter_frame_expression_stack_size() - 1; i >= 0; --i ) { - intptr_t* x = interpreter_frame_expression_stack_at(i); - st->print(" - stack at " INTPTR_FORMAT " = " INTPTR_FORMAT, x, *x); - st->fill_to(70); + intptr_t x = *interpreter_frame_expression_stack_at(i); + st->print(" - stack [" INTPTR_FORMAT "]", x); + st->fill_to(23); st->print_cr("; #%d", i); } // locks for synchronization - st->print_cr(" - monitorend = " INTPTR_FORMAT, interpreter_frame_monitor_end()); for (BasicObjectLock* current = interpreter_frame_monitor_end(); current < interpreter_frame_monitor_begin(); current = next_monitor_in_interpreter_frame(current)) { - st->print (" - lock at " INTPTR_FORMAT " = ", current->lock()); + st->print(" - obj ["); + current->obj()->print_value_on(st); + st->print_cr("]"); + st->print(" - lock ["); current->lock()->print_on(st); - st->cr(); - st->print (" - obj at " INTPTR_FORMAT " = " INTPTR_FORMAT " ", current->obj_addr(), *current->obj_addr()); - current->obj()->print_value_on(st); - st->cr(); + st->print_cr("]"); } - st->print_cr(" - monitorbegin = " INTPTR_FORMAT, interpreter_frame_monitor_begin()); - - // bcp/bcx - st->print (" - bcp at " INTPTR_FORMAT " = " INTPTR_FORMAT, interpreter_frame_bcx_addr(), interpreter_frame_bcp()); - st->fill_to(70); - st->print_cr("; @%d - %s", interpreter_frame_bci(), Bytecodes::name(interpreter_frame_method()->code_at(interpreter_frame_bci()))); + // monitor + st->print_cr(" - monitor[" INTPTR_FORMAT "]", interpreter_frame_monitor_begin()); + // bcp + st->print(" - bcp [" INTPTR_FORMAT "]", interpreter_frame_bcp()); + st->fill_to(23); + st->print_cr("; @%d", interpreter_frame_bci()); // locals - st->print_cr(" - locals at " INTPTR_FORMAT " = " INTPTR_FORMAT, interpreter_frame_locals_addr(), *interpreter_frame_locals_addr()); - // constant pool cache - st->print_cr(" - constant pool at " INTPTR_FORMAT " = " INTPTR_FORMAT, interpreter_frame_cache_addr(), *interpreter_frame_cache_addr()); - // method data - st->print_cr(" - method data at " INTPTR_FORMAT " = " INTPTR_FORMAT, interpreter_frame_mdx_addr(), *interpreter_frame_mdx_addr()); + st->print_cr(" - locals [" INTPTR_FORMAT "]", interpreter_frame_local_at(0)); // method - st->print (" - method at " INTPTR_FORMAT " = " INTPTR_FORMAT, interpreter_frame_method_addr(), *interpreter_frame_method_addr()); - st->fill_to(70); + st->print(" - method [" INTPTR_FORMAT "]", (address)interpreter_frame_method()); + st->fill_to(23); st->print("; "); interpreter_frame_method()->print_name(st); st->cr(); -#ifdef AMD64 - // last sp - st->print_cr(" - last sp at " INTPTR_FORMAT " = " INTPTR_FORMAT, interpreter_frame_last_sp_addr(), *interpreter_frame_last_sp_addr()); -#endif - // sender sp - st->print_cr(" - sender sp at " INTPTR_FORMAT " = " INTPTR_FORMAT, interpreter_frame_sender_sp_addr(), *interpreter_frame_sender_sp_addr()); - // old fp - st->print_cr(" - old fp at " INTPTR_FORMAT " = " INTPTR_FORMAT, link_addr(), *link_addr()); - // return address - st->print_cr(" - return pc at " INTPTR_FORMAT " = " INTPTR_FORMAT, sender_pc_addr(), *sender_pc_addr()); - - // locals - for (i = interpreter_frame_method()->max_locals() - 1; i >= 0; i--) { - intptr_t* x = interpreter_frame_local_at(i); - st->print (" - local at " INTPTR_FORMAT " = " INTPTR_FORMAT, x, *x); - st->fill_to(70); - st->print_cr("; #%d", i); - } - - // fp - st->print_cr(" - fp = " INTPTR_FORMAT, fp()); #endif } @@ -735,9 +712,8 @@ } else if (_cb->is_nmethod()) { Method* m = ((nmethod *)_cb)->method(); if (m != NULL) { - address code = _cb->code_begin(); m->name_and_sig_as_C_string(buf, buflen); - st->print("J %s [" PTR_FORMAT "+%d]", buf, code, pc() - code); + st->print("J %s", buf); } else { st->print("J " PTR_FORMAT, pc()); }
--- a/src/share/vm/runtime/frame.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/runtime/frame.hpp Tue Mar 12 11:38:52 2013 +0100 @@ -204,11 +204,9 @@ public: // Link (i.e., the pointer to the previous frame) intptr_t* link() const; - intptr_t** link_addr() const; void set_link(intptr_t* addr); // Return address - address* sender_pc_addr() const; address sender_pc() const; // Support for deoptimization @@ -305,7 +303,6 @@ jint interpreter_frame_expression_stack_size() const; intptr_t* interpreter_frame_sender_sp() const; - intptr_t** interpreter_frame_sender_sp_addr() const; #ifndef CC_INTERP // template based interpreter deoptimization support
--- a/src/share/vm/runtime/globals.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/runtime/globals.cpp Tue Mar 12 11:38:52 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
--- a/src/share/vm/runtime/globals.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/runtime/globals.hpp Tue Mar 12 11:38:52 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 @@ -1218,9 +1218,6 @@ notproduct(bool, TraceJVMCalls, false, \ "Trace JVM calls") \ \ - product(bool, TraceSignals, false, \ - "Trace signals and implicit exception handling") \ - \ product(ccstr, TraceJVMTI, NULL, \ "Trace flags for JVMTI functions and events") \ \ @@ -1252,7 +1249,7 @@ develop(bool, TraceClassInitialization, false, \ "Trace class initialization") \ \ - product(bool, TraceExceptions, false, \ + develop(bool, TraceExceptions, false, \ "Trace exceptions") \ \ develop(bool, TraceICs, false, \ @@ -1822,7 +1819,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 +1833,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'.") \ @@ -2621,9 +2618,6 @@ diagnostic(bool, PrintInterpreter, false, \ "Prints the generated interpreter code") \ \ - product(bool, PrintMachineCodeToFile, false, \ - "Prints the generated machine code to a file (int + comp)") \ - \ product(bool, UseInterpreter, true, \ "Use interpreter for non-compiled methods") \ \ @@ -3003,10 +2997,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 +3030,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 +3057,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, \
--- a/src/share/vm/runtime/globals_extension.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/runtime/globals_extension.hpp Tue Mar 12 11:38:52 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_<cmdline-arg> 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,
--- a/src/share/vm/runtime/init.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/runtime/init.cpp Tue Mar 12 11:38:52 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(); @@ -87,10 +87,6 @@ mutex_init(); chunkpool_init(); perfMemory_init(); - - if(PrintMachineCodeToFile) { - MachineCodePrinter::initialize(); - } }
--- a/src/share/vm/runtime/java.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/runtime/java.cpp Tue Mar 12 11:38:52 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" @@ -248,13 +249,10 @@ Runtime1::print_statistics(); Deoptimization::print_statistics(); SharedRuntime::print_statistics(); + nmethod::print_statistics(); } #endif /* COMPILER1 */ - if(PrintNMethodStatistics) { - nmethod::print_statistics(); - } - #ifdef COMPILER2 if ((PrintOptoStatistics || LogVMOutput || LogCompilation) && UseCompiler) { FlagSetting fs(DisplayVMOutput, DisplayVMOutput && PrintOptoStatistics); @@ -375,10 +373,6 @@ CompileBroker::print_times(); } - if(PrintNMethodStatistics) { - nmethod::print_statistics(); - } - if (PrintCodeCache) { MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); CodeCache::print();
--- a/src/share/vm/runtime/javaCalls.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/runtime/javaCalls.cpp Tue Mar 12 11:38:52 2013 +0100 @@ -39,21 +39,7 @@ #include "runtime/mutexLocker.hpp" #include "runtime/signature.hpp" #include "runtime/stubRoutines.hpp" -#ifdef HIGH_LEVEL_INTERPRETER -# include "graal/graalVMToInterpreter.hpp" -#endif -#ifdef TARGET_OS_FAMILY_linux -# include "thread_linux.inline.hpp" -#endif -#ifdef TARGET_OS_FAMILY_solaris -# include "thread_solaris.inline.hpp" -#endif -#ifdef TARGET_OS_FAMILY_windows -# include "thread_windows.inline.hpp" -#endif -#ifdef TARGET_OS_FAMILY_bsd -# include "thread_bsd.inline.hpp" -#endif +#include "runtime/thread.inline.hpp" // ----------------------------------------------------- // Implementation of JavaCallWrapper @@ -335,19 +321,10 @@ assert(THREAD->is_Java_thread(), "only JavaThreads can make JavaCalls"); // Need to wrap each and everytime, since there might be native code down the // stack that has installed its own exception handlers - os::os_exception_wrapper(call_helper, result, &method, NULL, args, THREAD); + os::os_exception_wrapper(call_helper, result, &method, args, THREAD); } -void JavaCalls::call(JavaValue* result, methodHandle method, nmethod* nm, JavaCallArguments* args, TRAPS) { - // Check if we need to wrap a potential OS exception handler around thread - // This is used for e.g. Win32 structured exception handlers - assert(THREAD->is_Java_thread(), "only JavaThreads can make JavaCalls"); - // Need to wrap each and everytime, since there might be native code down the - // stack that has installed its own exception handlers - os::os_exception_wrapper(call_helper, result, &method, nm, args, THREAD); -} - -void JavaCalls::call_helper(JavaValue* result, methodHandle* m, nmethod* nm, JavaCallArguments* args, TRAPS) { +void JavaCalls::call_helper(JavaValue* result, methodHandle* m, JavaCallArguments* args, TRAPS) { methodHandle method = *m; JavaThread* thread = (JavaThread*)THREAD; assert(thread->is_Java_thread(), "must be called by a java thread"); @@ -373,6 +350,7 @@ } #endif + #ifdef ASSERT { InstanceKlass* holder = method->method_holder(); // A klass might not be initialized since JavaCall's might be used during the executing of @@ -427,26 +405,18 @@ os::bang_stack_shadow_pages(); } +#ifdef GRAAL + nmethod* nm = args->alternative_target(); if (nm != NULL) { -#ifdef GRAAL if (nm->is_alive()) { ((JavaThread*) THREAD)->set_graal_alternate_call_target(nm->verified_entry_point()); entry_point = method->adapter()->get_i2c_entry(); } else { THROW(vmSymbols::MethodInvalidatedException()); } -#else - ShouldNotReachHere(); + } #endif - } -#ifdef HIGH_LEVEL_INTERPRETER - if (thread->high_level_interpreter_in_vm() && !method->is_native() && Interpreter::contains(entry_point)) { - assert(nm == NULL || !nm->is_alive(), "otherwise nm should be invoked"); - VMToInterpreter::execute(result, m, args, result->get_type(), thread); - oop_result_flag = false; // result already holds the correct value - } else -#endif // do call { JavaCallWrapper link(method, receiver, result, CHECK); { HandleMark hm(thread); // HandleMark used by HandleMarkCleaner @@ -482,6 +452,7 @@ } } + //-------------------------------------------------------------------------------------- // Implementation of JavaCallArguments
--- a/src/share/vm/runtime/javaCalls.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/runtime/javaCalls.hpp Tue Mar 12 11:38:52 2013 +0100 @@ -98,6 +98,9 @@ int _size; int _max_size; bool _start_at_zero; // Support late setting of receiver +#ifdef GRAAL + nmethod* _alternative_target; // Nmethod that should be called instead of normal target +#endif void initialize() { // Starts at first element to support set_receiver. @@ -107,6 +110,7 @@ _max_size = _default_size; _size = 0; _start_at_zero = false; + GRAAL_ONLY(_alternative_target = NULL;) } public: @@ -128,11 +132,22 @@ _max_size = max_size; _size = 0; _start_at_zero = false; + GRAAL_ONLY(_alternative_target = NULL;) } else { initialize(); } } +#ifdef GRAAL + void set_alternative_target(nmethod* target) { + _alternative_target = target; + } + + nmethod* alternative_target() { + return _alternative_target; + } +#endif + inline void push_oop(Handle h) { _is_oop[_size] = true; JNITypes::put_obj((oop)h.raw_value(), _value, _size); } @@ -148,12 +163,6 @@ inline void push_float(float f) { _is_oop[_size] = false; JNITypes::put_float(f, _value, _size); } - inline oop* get_raw_oop(int& pos) { return (oop*)JNITypes::get_obj(_value, pos); } - inline jint get_int(int& pos) { return JNITypes::get_int(_value, pos); } - inline jdouble get_double(int& pos) { return JNITypes::get_double(_value, pos); } - inline jlong get_long(int& pos) { return JNITypes::get_long(_value, pos); } - inline jfloat get_float(int& pos) { return JNITypes::get_float(_value, pos); } - // receiver Handle receiver() { assert(_size > 0, "must at least be one argument"); @@ -185,8 +194,8 @@ // class JavaCalls: AllStatic { - static void call_helper(JavaValue* result, methodHandle* method, nmethod* nm, JavaCallArguments* args, TRAPS); -public: + static void call_helper(JavaValue* result, methodHandle* method, JavaCallArguments* args, TRAPS); + public: // Optimized Constuctor call static void call_default_constructor(JavaThread* thread, methodHandle method, Handle receiver, TRAPS); @@ -225,7 +234,6 @@ // Low-level interface static void call(JavaValue* result, methodHandle method, JavaCallArguments* args, TRAPS); - static void call(JavaValue* result, methodHandle method, nmethod* nm, JavaCallArguments* args, TRAPS); }; #endif // SHARE_VM_RUNTIME_JAVACALLS_HPP
--- a/src/share/vm/runtime/os.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/runtime/os.cpp Tue Mar 12 11:38:52 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 @@ -1135,6 +1149,9 @@ #ifdef __APPLE__ "%/lib/JObjC.jar:" #endif +#ifdef GRAAL + "%/lib/graal.jar:" +#endif "%/classes"; char* sysclasspath = format_boot_path(classpath_format, home, home_len, fileSep, pathSep); if (sysclasspath == NULL) return false;
--- a/src/share/vm/runtime/os.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/runtime/os.hpp Tue Mar 12 11:38:52 2013 +0100 @@ -79,7 +79,7 @@ }; // Typedef for structured exception handling support -typedef void (*java_call_t)(JavaValue* value, methodHandle* method, nmethod* nm, JavaCallArguments* args, Thread* thread); +typedef void (*java_call_t)(JavaValue* value, methodHandle* method, JavaCallArguments* args, Thread* thread); class os: AllStatic { public: @@ -658,7 +658,7 @@ static void init_random(long initval); // initialize random sequence // Structured OS Exception support - static void os_exception_wrapper(java_call_t f, JavaValue* value, methodHandle* method, nmethod* nm, JavaCallArguments* args, Thread* thread); + static void os_exception_wrapper(java_call_t f, JavaValue* value, methodHandle* method, JavaCallArguments* args, Thread* thread); // On Windows this will create an actual minidump, on Linux/Solaris it will simply check core dump limits static void check_or_create_dump(void* exceptionRecord, void* contextRecord, char* buffer, size_t bufferSize);
--- a/src/share/vm/runtime/reflectionUtils.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/runtime/reflectionUtils.cpp Tue Mar 12 11:38:52 2013 +0100 @@ -26,9 +26,6 @@ #include "classfile/javaClasses.hpp" #include "memory/universe.inline.hpp" #include "runtime/reflectionUtils.hpp" -#ifdef GRAAL -#include "graal/graalJavaAccess.hpp" -#endif KlassStream::KlassStream(instanceKlassHandle klass, bool local_only, bool classes_only) { _klass = klass;
--- a/src/share/vm/runtime/safepoint.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/runtime/safepoint.cpp Tue Mar 12 11:38:52 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,16 +73,13 @@ # 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 -#ifdef GRAAL -#include "graal/graalGlobals.hpp" -#endif // -------------------------------------------------------------------------------------------------- // Implementation of Safepoint begin/end @@ -106,7 +104,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 +112,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 +481,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();
--- a/src/share/vm/runtime/sharedRuntime.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/runtime/sharedRuntime.cpp Tue Mar 12 11:38:52 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)) @@ -772,9 +773,6 @@ #ifdef GRAAL address SharedRuntime::deoptimize_for_implicit_exception(JavaThread* thread, address pc, nmethod* nm, int deopt_reason) { assert(deopt_reason > Deoptimization::Reason_none && deopt_reason < Deoptimization::Reason_LIMIT, "invalid deopt reason"); - if (TraceSignals) { - tty->print_cr(err_msg("Deoptimizing on implicit exception at relative pc=%d in method %s", pc - nm->entry_point(), nm->method()->name()->as_C_string())); - } thread->_ScratchA = (intptr_t)pc; thread->_ScratchB = Deoptimization::make_trap_request((Deoptimization::DeoptReason)deopt_reason, Deoptimization::Action_reinterpret); return (SharedRuntime::deopt_blob()->implicit_exception_uncommon_trap()); @@ -898,9 +896,6 @@ #endif #ifdef GRAAL if (nm->is_compiled_by_graal()) { - if (TraceSignals) { - tty->print_cr("Graal implicit div0"); - } target_pc = deoptimize_for_implicit_exception(thread, pc, nm, Deoptimization::Reason_div0_check); } else { #endif @@ -2868,10 +2863,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
--- a/src/share/vm/runtime/sharedRuntime.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/runtime/sharedRuntime.hpp Tue Mar 12 11:38:52 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,
--- a/src/share/vm/runtime/stackValue.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/runtime/stackValue.cpp Tue Mar 12 11:38:52 2013 +0100 @@ -118,22 +118,6 @@ val = (oop)NULL; } #endif -#ifndef PRODUCT - if (val != NULL && !val->is_oop()) { - ResourceMark rm; - tty->print_cr("found wrong oop " INTPTR_FORMAT " at location " INTPTR_FORMAT " (%d):", val, value_addr, val->is_oop()); - if (fr->cb() != NULL) { - CodeBlob* cb = fr->cb(); - if (cb->is_nmethod()) { - nmethod* nm = (nmethod*)cb; - tty->print_cr("method is %s", nm->method()->name()->as_C_string()); - } - } - sv->print(); - tty->print_cr(""); - tty->print_cr("one less %d; one more %d", (*(((oop *)value_addr) - 1))->is_oop(), (*(((oop *)value_addr) + 1))->is_oop()); - } -#endif Handle h(val); // Wrap a handle around the oop return new StackValue(h); }
--- a/src/share/vm/runtime/synchronizer.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/runtime/synchronizer.cpp Tue Mar 12 11:38:52 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
--- a/src/share/vm/runtime/thread.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/runtime/thread.cpp Tue Mar 12 11:38:52 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 @@ -1409,7 +1410,6 @@ // Set the claimed par_id to -1 (ie not claiming any par_ids) set_claimed_par_id(-1); - _env = NULL; _buffer_blob = NULL; set_saved_exception_pc(NULL); set_threadObj(NULL); @@ -1439,12 +1439,7 @@ _doing_unsafe_access = false; _stack_guard_state = stack_guard_unused; #ifdef GRAAL - _graal_deopt_info = NULL; _graal_alternate_call_target = NULL; - _debug_scope = NULL; -#endif -#ifdef HIGH_LEVEL_INTERPRETER - _high_level_interpreter_in_vm = false; #endif _exception_oop = NULL; _exception_pc = 0; @@ -1496,17 +1491,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) { @@ -1514,7 +1509,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; } @@ -1561,10 +1556,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); @@ -1910,19 +1905,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(); @@ -1950,7 +1952,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) { @@ -1978,11 +1980,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; @@ -2187,9 +2189,7 @@ // Do not throw asynchronous exceptions against the compiler thread // (the compiler thread should not be a Java thread -- fix in 1.4.2) - - // (thomaswue) May we do this? - //if (is_Compiler_thread()) return; + if (is_Compiler_thread()) return; { // Actually throw the Throwable against the target Thread - however @@ -2776,9 +2776,6 @@ // around using this function f->do_oop((oop*) &_threadObj); f->do_oop((oop*) &_vm_result); -#ifdef GRAAL - f->do_oop((oop*) &_graal_deopt_info); -#endif f->do_oop((oop*) &_exception_oop); f->do_oop((oop*) &_pending_async_exception); @@ -3236,6 +3233,7 @@ // Create a CompilerThread CompilerThread::CompilerThread(CompileQueue* queue, CompilerCounters* counters) : JavaThread(&compiler_thread_entry) { + _env = NULL; _log = NULL; _task = NULL; _queue = queue; @@ -3613,7 +3611,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 @@ -3627,7 +3625,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 @@ -3752,28 +3750,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)) { @@ -4222,7 +4198,7 @@ } } -#ifndef SERIALGC +#if INCLUDE_ALL_GCS // Used by ParallelScavenge void Threads::create_thread_roots_tasks(GCTaskQueue* q) { ALL_JAVA_THREADS(p) { @@ -4238,7 +4214,7 @@ } q->enqueue(new ThreadRootsMarkingTask(VMThread::vm_thread())); } -#endif // SERIALGC +#endif // INCLUDE_ALL_GCS void Threads::nmethods_do(CodeBlobClosure* cf) { ALL_JAVA_THREADS(p) { @@ -4346,13 +4322,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; @@ -4365,11 +4341,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);
--- a/src/share/vm/runtime/thread.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/runtime/thread.hpp Tue Mar 12 11:38:52 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" @@ -768,13 +769,10 @@ JavaThread* _next; // The next thread in the Threads list oop _threadObj; // The Java level thread object - // (thomaswue) Necessary for holding a compilation buffer and ci environment. + // (thomaswue) Necessary for holding a compilation buffer. // Moved up from CompilerThread to JavaThread in order to enable code // installation from Java application code. BufferBlob* _buffer_blob; - ciEnv* _env; - bool _is_compiling; - #ifdef ASSERT private: int _java_call_counter; @@ -903,14 +901,8 @@ private: #ifdef GRAAL - volatile oop _graal_deopt_info; address _graal_alternate_call_target; - DebugScopedValue* _debug_scope; #endif -#ifdef HIGH_LEVEL_INTERPRETER - bool _high_level_interpreter_in_vm; -#endif - StackGuardState _stack_guard_state; nmethod* _scanned_nmethod; // nmethod being scanned by the sweeper @@ -923,6 +915,9 @@ volatile address _exception_handler_pc; // PC for handler of exception volatile int _is_method_handle_return; // true (== 1) if the current exception PC is a MethodHandle call site. + // support for compilation + bool _is_compiling; // is true if a compilation is active inthis thread (one compilation per thread possible) + // support for JNI critical regions jint _jni_active_critical; // count of entries into JNI critical region @@ -944,7 +939,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. @@ -956,7 +951,7 @@ static DirtyCardQueueSet _dirty_card_queue_set; void flush_barrier_queues(); -#endif // !SERIALGC +#endif // INCLUDE_ALL_GCS friend class VMThread; friend class ThreadWaitTransition; @@ -982,13 +977,7 @@ struct JNINativeInterface_* get_jni_functions() { return (struct JNINativeInterface_ *)_jni_environment.functions; } - - bool is_compiling() const { return _is_compiling; } - void set_compiling(bool b) { _is_compiling = b; } - // Get/set the thread's compilation environment. - ciEnv* env() { return _env; } - void set_env(ciEnv* env) { _env = env; } BufferBlob* get_buffer_blob() { return _buffer_blob; } void set_buffer_blob(BufferBlob* b) { _buffer_blob = b; }; @@ -1018,6 +1007,10 @@ // Testers virtual bool is_Java_thread() const { return true; } + // compilation + void set_is_compiling(bool f) { _is_compiling = f; } + bool is_compiling() const { return _is_compiling; } + // Thread chain operations JavaThread* next() const { return _next; } void set_next(JavaThread* p) { _next = p; } @@ -1282,17 +1275,7 @@ void set_deferred_card_mark(MemRegion mr) { _deferred_card_mark = mr; } #ifdef GRAAL - oop graal_deopt_info() const { return _graal_deopt_info; } - void set_graal_deopt_info(oop o) { _graal_deopt_info = o; } - void set_graal_alternate_call_target(address a) { _graal_alternate_call_target = a; } - - DebugScopedValue* debug_scope() const { return _debug_scope; } - void set_debug_scope(DebugScopedValue* ds) { _debug_scope = ds; } -#endif -#ifdef HIGH_LEVEL_INTERPRETER - bool high_level_interpreter_in_vm() { return _high_level_interpreter_in_vm; } - void set_high_level_interpreter_in_vm(bool value) { _high_level_interpreter_in_vm = value; } #endif // Exception handling for compiled methods @@ -1375,12 +1358,8 @@ static ByteSize saved_exception_pc_offset() { return byte_offset_of(JavaThread, _saved_exception_pc ); } static ByteSize osthread_offset() { return byte_offset_of(JavaThread, _osthread ); } #ifdef GRAAL - static ByteSize graal_deopt_info_offset() { return byte_offset_of(JavaThread, _graal_deopt_info ); } static ByteSize graal_alternate_call_target_offset() { return byte_offset_of(JavaThread, _graal_alternate_call_target); } #endif -#ifdef HIGH_LEVEL_INTERPRETER - static ByteSize high_level_interpreter_in_vm_offset() { return byte_offset_of(JavaThread, _high_level_interpreter_in_vm); } -#endif static ByteSize exception_oop_offset() { return byte_offset_of(JavaThread, _exception_oop ); } static ByteSize exception_pc_offset() { return byte_offset_of(JavaThread, _exception_pc ); } static ByteSize exception_handler_pc_offset() { return byte_offset_of(JavaThread, _exception_handler_pc); } @@ -1393,10 +1372,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; } @@ -1685,7 +1664,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() { @@ -1697,7 +1676,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 @@ -1716,11 +1695,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 @@ -1836,6 +1815,7 @@ private: CompilerCounters* _counters; + ciEnv* _env; CompileLog* _log; CompileTask* _task; CompileQueue* _queue; @@ -1849,18 +1829,15 @@ bool is_Compiler_thread() const { return true; } // Hide this compiler thread from external view. - // (thomaswue) For Graal, the compiler thread should be visible. - bool is_hidden_from_external_view() const { -#ifdef GRAALVM - return !DebugGraal; -#else - return true; -#endif - } + bool is_hidden_from_external_view() const { return true; } CompileQueue* queue() { return _queue; } CompilerCounters* counters() { return _counters; } + // Get/set the thread's compilation environment. + ciEnv* env() { return _env; } + void set_env(ciEnv* env) { _env = env; } + // Get/set the thread's logging information CompileLog* log() { return _log; } void init_log(CompileLog* log) {
--- a/src/share/vm/runtime/vframe.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/runtime/vframe.cpp Tue Mar 12 11:38:52 2013 +0100 @@ -266,8 +266,8 @@ // Get oopmap describing oops and int for current bci InterpreterOopMap oop_mask; - if (PrintDeoptimizationDetails) { - methodHandle m_h(method()); + if (TraceDeoptimization && Verbose) { + methodHandle m_h(thread(), method()); OopMapCache::compute_one_oop_map(m_h, bci(), &oop_mask); } else { method()->mask_for(bci(), &oop_mask); @@ -333,7 +333,7 @@ InterpreterOopMap oop_mask; // Get oopmap describing oops and int for current bci - if (PrintDeoptimizationDetails) { + if (TraceDeoptimization && Verbose) { methodHandle m_h(method()); OopMapCache::compute_one_oop_map(m_h, bci(), &oop_mask); } else {
--- a/src/share/vm/runtime/vframeArray.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/runtime/vframeArray.cpp Tue Mar 12 11:38:52 2013 +0100 @@ -63,7 +63,7 @@ _method = vf->method(); _bci = vf->raw_bci(); _reexecute = vf->should_reexecute(); - + int index; // Get the monitors off-stack @@ -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 @@ -431,6 +429,11 @@ RegisterMap map(thread); vframe* f = vframe::new_vframe(iframe(), &map, thread); f->print(); + + tty->print_cr("locals size %d", locals()->size()); + tty->print_cr("expression size %d", expressions()->size()); + + method()->print_value(); tty->cr(); // method()->print_codes(); } else if (TraceDeoptimization) {
--- a/src/share/vm/runtime/vframe_hp.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/runtime/vframe_hp.cpp Tue Mar 12 11:38:52 2013 +0100 @@ -70,12 +70,6 @@ } } - if (PrintDeoptimizationDetails) { - tty->print_cr("bci=%d length=%d", this->bci(), length); - tty->print_cr(err_msg("method name = %s", this->method()->name()->as_C_string())); - tty->print_cr("relative pc=%d", this->fr().pc() - this->nm()->code_begin()); - } - for( int i = 0; i < length; i++ ) { result->add( create_stack_value(scv_list->at(i)) ); }
--- a/src/share/vm/runtime/vframe_hp.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/runtime/vframe_hp.hpp Tue Mar 12 11:38:52 2013 +0100 @@ -66,7 +66,7 @@ // Returns SynchronizationEntryBCI or bci() (used for synchronization) int raw_bci() const; - //protected: + protected: ScopeDesc* _scope;
--- a/src/share/vm/runtime/vmStructs.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/runtime/vmStructs.cpp Tue Mar 12 11:38:52 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" @@ -208,7 +209,7 @@ // type name, indicating an "opaque" type to the serviceability agent. // NOTE: there is an interdependency between this file and -// HotSpotJavaTypeDataBase.java, which parses the type strings. +// HotSpotTypeDataBase.java, which parses the type strings. #ifndef REG_COUNT #define REG_COUNT 0 @@ -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<u1>*) \ 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<Metablock>*) \ declare_toplevel_type(FreeList<Metablock>*) \ declare_toplevel_type(FreeList<Metablock>) \ - declare_toplevel_type(MetablockTreeDictionary*) \ - declare_type(MetablockTreeDictionary, FreeBlockDictionary<Metablock>) + declare_type(MetablockTreeDictionary, FreeBlockDictionary<Metablock>) //-------------------------------------------------------------------------------- @@ -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 */ \ @@ -2382,32 +2384,26 @@ declare_constant(Location::on_stack) \ declare_constant(Location::in_register) \ \ - /* TODO (chaeubl) those constants should be graal/c1/c2 specific */ \ - /*declare_constant(Deoptimization::Reason_many)*/ \ - /*declare_constant(Deoptimization::Reason_none)*/ \ - /*declare_constant(Deoptimization::Reason_null_check)*/ \ - /*declare_constant(Deoptimization::Reason_range_check)*/ \ - /*declare_constant(Deoptimization::Reason_class_check)*/ \ - /*declare_constant(Deoptimization::Reason_array_check)*/ \ - /*declare_constant(Deoptimization::Reason_unreached)*/ \ - /*declare_constant(Deoptimization::Reason_constraint)*/ \ - /*declare_constant(Deoptimization::Reason_div0_check)*/ \ - /*declare_constant(Deoptimization::Reason_type_checked_inlining)*/ \ - /*declare_constant(Deoptimization::Reason_optimized_type_check)*/ \ - /*declare_constant(Deoptimization::Reason_not_compiled_exception_handler)*/ \ - /*declare_constant(Deoptimization::Reason_unresolved)*/ \ - /*declare_constant(Deoptimization::Reason_jsr_mismatch)*/ \ - /*declare_constant(Deoptimization::Reason_LIMIT)*/ \ - /*declare_constant(Deoptimization::Reason_RECORDED_LIMIT)*/ \ - /*declare_constant(Deoptimization::Reason_null_assert)*/ \ - /*declare_constant(Deoptimization::Reason_intrinsic)*/ \ - /*declare_constant(Deoptimization::Reason_bimorphic)*/ \ - /*declare_constant(Deoptimization::Reason_unloaded)*/ \ - /*declare_constant(Deoptimization::Reason_uninitialized) */ \ - /*declare_constant(Deoptimization::Reason_unhandled)*/ \ - /*declare_constant(Deoptimization::Reason_age)*/ \ - /*declare_constant(Deoptimization::Reason_predicate)*/ \ - /*declare_constant(Deoptimization::Reason_loop_limit_check)*/ \ + declare_constant(Deoptimization::Reason_many) \ + declare_constant(Deoptimization::Reason_none) \ + declare_constant(Deoptimization::Reason_null_check) \ + declare_constant(Deoptimization::Reason_null_assert) \ + declare_constant(Deoptimization::Reason_range_check) \ + declare_constant(Deoptimization::Reason_class_check) \ + declare_constant(Deoptimization::Reason_array_check) \ + declare_constant(Deoptimization::Reason_intrinsic) \ + declare_constant(Deoptimization::Reason_bimorphic) \ + declare_constant(Deoptimization::Reason_unloaded) \ + declare_constant(Deoptimization::Reason_uninitialized) \ + declare_constant(Deoptimization::Reason_unreached) \ + declare_constant(Deoptimization::Reason_unhandled) \ + declare_constant(Deoptimization::Reason_constraint) \ + declare_constant(Deoptimization::Reason_div0_check) \ + declare_constant(Deoptimization::Reason_age) \ + declare_constant(Deoptimization::Reason_predicate) \ + declare_constant(Deoptimization::Reason_loop_limit_check) \ + declare_constant(Deoptimization::Reason_LIMIT) \ + declare_constant(Deoptimization::Reason_RECORDED_LIMIT) \ \ /*********************/ \ /* Matcher (C2 only) */ \ @@ -2792,7 +2788,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 +2798,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 +2832,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 +2843,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 +2874,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 +2932,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 +2942,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 +2971,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 +2982,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 +3037,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 +3045,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,
--- a/src/share/vm/runtime/vmStructs.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/runtime/vmStructs.hpp Tue Mar 12 11:38:52 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
--- a/src/share/vm/runtime/vm_version.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/runtime/vm_version.cpp Tue Mar 12 11:38:52 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
--- a/src/share/vm/services/attachListener.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/services/attachListener.cpp Tue Mar 12 11:38:52 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 },
--- a/src/share/vm/services/attachListener.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/services/attachListener.hpp Tue Mar 12 11:38:52 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:
--- a/src/share/vm/services/classLoadingService.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/services/classLoadingService.cpp Tue Mar 12 11:38:52 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
--- a/src/share/vm/services/classLoadingService.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/services/classLoadingService.hpp Tue Mar 12 11:38:52 2013 +0100 @@ -28,6 +28,7 @@ #include "runtime/handles.hpp" #include "runtime/perfData.hpp" #include "utilities/growableArray.hpp" +#include "utilities/macros.hpp" class InstanceKlass;
--- a/src/share/vm/services/diagnosticCommand.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/services/diagnosticCommand.cpp Tue Mar 12 11:38:52 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<VMUptimeDCmd>(true, false)); DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<SystemGCDCmd>(true, false)); DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<RunFinalizationDCmd>(true, false)); -#if INCLUDE_SERVICES // Heap dumping supported +#if INCLUDE_SERVICES // Heap dumping/inspection supported DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<HeapDumpDCmd>(true, false)); + DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<ClassHistogramDCmd>(true, false)); + DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<ClassStatsDCmd>(true, false)); #endif // INCLUDE_SERVICES - DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<ClassHistogramDCmd>(true, false)); DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<ThreadDumpDCmd>(true, false)); - //Enhanced JMX Agent Support DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<JMXStartRemoteDCmd>(true,false)); DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<JMXStartLocalDCmd>(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
--- a/src/share/vm/services/diagnosticCommand.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/services/diagnosticCommand.hpp Tue Mar 12 11:38:52 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<bool> _all; @@ -197,6 +198,27 @@ virtual void execute(TRAPS); }; +class ClassStatsDCmd : public DCmdWithParser { +protected: + DCmdArgument<bool> _all; + DCmdArgument<bool> _csv; + DCmdArgument<bool> _help; + DCmdArgument<char*> _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<char *> _jmxremote_ssl_need_client_auth; DCmdArgument<char *> _jmxremote_ssl_config_file; + // JDP support + // Keep autodiscovery char* not bool to pass true/false + // as property value to java level. + DCmdArgument<char *> _jmxremote_autodiscovery; + DCmdArgument<jlong> _jdp_port; + DCmdArgument<char *> _jdp_address; + DCmdArgument<char *> _jdp_source_addr; + DCmdArgument<jlong> _jdp_ttl; + DCmdArgument<jlong> _jdp_pause; + public: JMXStartRemoteDCmd(outputStream *output, bool heap_allocated);
--- a/src/share/vm/services/g1MemoryPool.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/services/g1MemoryPool.hpp Tue Mar 12 11:38:52 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
--- a/src/share/vm/services/heapDumper.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/services/heapDumper.cpp Tue Mar 12 11:38:52 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:
--- a/src/share/vm/services/management.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/services/management.cpp Tue Mar 12 11:38:52 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;
--- a/src/share/vm/services/memBaseline.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/services/memBaseline.cpp Tue Mar 12 11:38:52 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 };
--- a/src/share/vm/services/memPtr.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/services/memPtr.cpp Tue Mar 12 11:38:52 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);
--- a/src/share/vm/services/memPtr.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/services/memPtr.hpp Tue Mar 12 11:38:52 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; ) }; /*
--- a/src/share/vm/services/memRecorder.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/services/memRecorder.cpp Tue Mar 12 11:38:52 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)FixedSizeMemPointerArray<SeqMemPointerRecordEx, @@ -151,11 +151,12 @@ } -#ifdef ASSERT void MemRecorder::set_generation() { _generation = SequenceGenerator::current_generation(); } +#ifdef ASSERT + void MemRecorder::check_dup_seq(jint seq) const { MemPointerArrayIteratorImpl itr(_pointer_records); MemPointerRecord* rc = (MemPointerRecord*)itr.current();
--- a/src/share/vm/services/memRecorder.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/services/memRecorder.hpp Tue Mar 12 11:38:52 2013 +0100 @@ -213,7 +213,7 @@ // used for linked list MemRecorder* _next; // active recorder can only record a certain generation data - debug_only(unsigned long _generation;) + unsigned long _generation; protected: _NOINLINE_ MemRecorder(); @@ -251,6 +251,8 @@ SequencedRecordIterator pointer_itr(); + // return the generation of this recorder which it belongs to + unsigned long get_generation() const { return _generation; } protected: // number of MemRecorder instance static volatile jint _instance_count; @@ -263,7 +265,7 @@ static int sort_record_fn(const void* e1, const void* e2); debug_only(void check_dup_seq(jint seq) const;) - debug_only(void set_generation();) + void set_generation(); }; #endif // SHARE_VM_SERVICES_MEM_RECORDER_HPP
--- a/src/share/vm/services/memReporter.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/services/memReporter.hpp Tue Mar 12 11:38:52 2013 +0100 @@ -29,6 +29,7 @@ #include "services/memBaseline.hpp" #include "services/memTracker.hpp" #include "utilities/ostream.hpp" +#include "utilities/macros.hpp" #if INCLUDE_NMT
--- a/src/share/vm/services/memSnapshot.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/services/memSnapshot.cpp Tue Mar 12 11:38:52 2013 +0100 @@ -528,7 +528,8 @@ // an arena record can be followed by a size record, we need to remove both if (matched_rec->is_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(); } }
--- a/src/share/vm/services/memTrackWorker.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/services/memTrackWorker.cpp Tue Mar 12 11:38:52 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
--- a/src/share/vm/services/memTrackWorker.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/services/memTrackWorker.hpp Tue Mar 12 11:38:52 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)); }
--- a/src/share/vm/services/memTracker.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/services/memTracker.cpp Tue Mar 12 11:38:52 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);
--- a/src/share/vm/services/memTracker.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/services/memTracker.hpp Tue Mar 12 11:38:52 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
--- a/src/share/vm/services/memoryPool.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/services/memoryPool.cpp Tue Mar 12 11:38:52 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,
--- a/src/share/vm/services/memoryPool.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/services/memoryPool.hpp Tue Mar 12 11:38:52 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 {
--- a/src/share/vm/services/memoryService.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/services/memoryService.cpp Tue Mar 12 11:38:52 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<MemoryPool*>* MemoryService::_pools_list = new (ResourceObj::C_HEAP, mtInternal) GrowableArray<MemoryPool*>(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:
--- a/src/share/vm/services/psMemoryPool.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/services/psMemoryPool.hpp Tue Mar 12 11:38:52 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:
--- a/src/share/vm/services/runtimeService.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/services/runtimeService.cpp Tue Mar 12 11:38:52 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);
--- a/src/share/vm/utilities/accessFlags.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/utilities/accessFlags.cpp Tue Mar 12 11:38:52 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");
--- a/src/share/vm/utilities/accessFlags.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/utilities/accessFlags.hpp Tue Mar 12 11:38:52 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) {
--- a/src/share/vm/utilities/constantTag.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/utilities/constantTag.cpp Tue Mar 12 11:38:52 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 :
--- a/src/share/vm/utilities/constantTag.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/utilities/constantTag.hpp Tue Mar 12 11:38:52 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() {
--- a/src/share/vm/utilities/debug.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/utilities/debug.cpp Tue Mar 12 11:38:52 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) { @@ -842,37 +830,3 @@ #endif #endif // !PRODUCT - -#ifdef GRAAL - -DebugScopedValue::DebugScopedValue(const char* file, int line) { - _file = file; - _line = line; - Thread* thread = Thread::current(); - if (thread != NULL && thread->is_Java_thread()) { - JavaThread* javaThread = (JavaThread*) thread; - _parent = javaThread->debug_scope(); - javaThread->set_debug_scope(this); - } else { - _parent = NULL; - } -} - -DebugScopedValue::~DebugScopedValue() { - Thread* thread = Thread::current(); - if (thread != NULL && thread->is_Java_thread()) { - JavaThread* javaThread = (JavaThread*) thread; - javaThread->set_debug_scope(_parent); - _parent = NULL; - } -} - -void DebugScopedValue::print(outputStream* st) { - st->print("%s:%d: ", _file, _line); - print_on(st); -} - -void DebugScopedScalar::print_on(outputStream* st) { - st->print("int: %d, char: %c, long: %ld, hex: %p", _value, _value, _value, _value); -} -#endif
--- a/src/share/vm/utilities/debug.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/utilities/debug.hpp Tue Mar 12 11:38:52 2013 +0100 @@ -30,35 +30,6 @@ #include <stdarg.h> -#ifdef GRAAL -// Scopes a value that may be of interest in a crash log. -class DebugScopedValue { -protected: - DebugScopedValue *_parent; - const char* _file; - int _line; -public: - DebugScopedValue(const char* file, int line); - ~DebugScopedValue(); - void print(outputStream* st); - virtual void print_on(outputStream* st) = 0; - DebugScopedValue* parent() { return _parent; } -}; - -class DebugScopedScalar : DebugScopedValue { -private: - void* _value; -public: - DebugScopedScalar(const char* file, int line, void* v) : DebugScopedValue(file, line), _value(v) {} - void print_on(outputStream* st); -}; -#define DS_SCALAR(val) DebugScopedScalar __dss__(__FILE__, __LINE__, (void*) val) -#define DS_SCALAR1(name, val) DebugScopedScalar name(__FILE__, __LINE__, (void*) val) -#else -#define DS_SCALAR(name) do {} while (0) -#define DS_SCALAR1(name, val) do {} while (0) -#endif - // Simple class to format the ctor arguments into a fixed-sized buffer. class FormatBufferBase { protected:
--- a/src/share/vm/utilities/machineCodePrinter.cpp Tue Mar 12 11:38:24 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,66 +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. - */ - -#include "precompiled.hpp" -#include "code/stubs.hpp" -#include "compiler/disassembler.hpp" -#include "runtime/thread.hpp" -#include "utilities/machineCodePrinter.hpp" -#include "utilities/ostream.hpp" - -fileStream* MachineCodePrinter::_st = NULL; -volatile int MachineCodePrinter::_write_lock = 0; - -void MachineCodePrinter::initialize() { - _st = new (ResourceObj::C_HEAP, mtInternal) fileStream("machineCode.txt"); -} - -void MachineCodePrinter::print(nmethod* nm) { - lock(); - Disassembler::decode(nm, _st); - unlock(); -} - -void MachineCodePrinter::print(CodeBlob* cb) { - lock(); - Disassembler::decode(cb, _st); - unlock(); -} - -void MachineCodePrinter::print(StubQueue* stub_queue) { - lock(); - stub_queue->print_on(_st); - unlock(); -} - -void MachineCodePrinter::flush() { - _st->flush(); -} - -void MachineCodePrinter::lock() { - Thread::SpinAcquire(&_write_lock, "Put"); -} - -void MachineCodePrinter::unlock() { - Thread::SpinRelease(&_write_lock); -}
--- a/src/share/vm/utilities/machineCodePrinter.hpp Tue Mar 12 11:38:24 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,47 +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. - */ - -#ifndef SHARE_VM_UTILITIES_MACHINE_CODE_PRINTER_HPP -#define SHARE_VM_UTILITIES_MACHINE_CODE_PRINTER_HPP - -#include "memory/allocation.hpp" -#include "utilities/ostream.hpp" - -class MachineCodePrinter : public AllStatic { -private: - static fileStream* _st; - static volatile int _write_lock; - -public: - static void initialize(); - static void print(nmethod* nm); - static void print(CodeBlob* cb); - static void print(StubQueue* stub_queue); - static void flush(); - -private: - static void lock(); - static void unlock(); -}; - -#endif // SHARE_VM_UTILITIES_MACHINE_CODE_PRINTER_HPP
--- a/src/share/vm/utilities/macros.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/utilities/macros.hpp Tue Mar 12 11:38:52 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 @@ -201,14 +201,6 @@ #define NOT_GRAALVM(code) code #endif // GRAAL -#ifdef HIGH_LEVEL_INTERPRETER -#define HIGH_LEVEL_INTERPRETER_ONLY(code) code -#define NOT_HIGH_LEVEL_INTERPRETER(code) -#else -#define HIGH_LEVEL_INTERPRETER_ONLY(code) -#define NOT_HIGH_LEVEL_INTERPRETER(code) code -#endif // HIGH_LEVEL_INTERPRETER - #ifdef TIERED #define TIERED_ONLY(code) code #define NOT_TIERED(code)
--- a/src/share/vm/utilities/ostream.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/utilities/ostream.cpp Tue Mar 12 11:38:52 2013 +0100 @@ -102,7 +102,6 @@ result_len = strlen(result); } else { DEBUG_ONLY(warning("increase O_BUFLEN in ostream.hpp -- output truncated");) - result = buffer; result_len = buflen - 1; buffer[result_len] = 0; @@ -432,7 +431,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 +440,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 +448,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 +464,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 +477,7 @@ if (NumberOfGCLogFiles == 1) { // rotate in same file rewind(); - _bytes_writen = 0L; + _bytes_written = 0L; return; } @@ -492,7 +493,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", @@ -656,9 +657,7 @@ // Print it as a java-style property list. // System properties don't generally contain newlines, so don't bother with unparsing. for (SystemProperty* p = Arguments::system_properties(); p != NULL; p = p->next()) { - xs->text()->print(p->key() ? p->key() : ""); - xs->text()->print("="); - xs->text()->print_cr(p->value() ? p->value() : ""); + xs->text()->print_cr("%s=%s", p->key(), p->value()); } xs->tail("properties"); }
--- a/src/share/vm/utilities/ostream.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/utilities/ostream.hpp Tue Mar 12 11:38:52 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);
--- a/src/share/vm/utilities/top.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/utilities/top.hpp Tue Mar 12 11:38:52 2013 +0100 @@ -33,18 +33,18 @@ #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 +#ifdef COMPILER2 +#include "opto/c2_globals.hpp" +#endif #ifdef GRAAL #include "graal/graalGlobals.hpp" #endif -#ifdef COMPILER2 -#include "opto/c2_globals.hpp" -#endif // THIS FILE IS INTESIONALLY LEFT EMPTY // IT IS USED TO MINIMIZE THE NUMBER OF DEPENDENCIES IN includeDB
--- a/src/share/vm/utilities/vmError.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/utilities/vmError.cpp Tue Mar 12 11:38:52 2013 +0100 @@ -491,30 +491,6 @@ print_bug_submit_message(st, _thread); } -#ifdef GRAAL - STEP(67, "(printing debug scope)" ) - - if (_verbose) { - if (_thread != NULL && _thread->is_Java_thread()) { - JavaThread* javaThread = (JavaThread*) _thread; - DebugScopedValue* ds = javaThread->debug_scope(); - int level = 0; - while (ds != NULL) { - if (level == 0) { - st->cr(); - st->print_cr("--------------- D E B U G S C O P E ---------------"); - st->cr(); - } - st->print("%d: ", level); - ds->print(st); - st->cr(); - ds = ds->parent(); - level++; - } - } - } -#endif - STEP(70, "(printing thread)" ) if (_verbose) {
--- a/src/share/vm/utilities/yieldingWorkgroup.cpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/utilities/yieldingWorkgroup.cpp Tue Mar 12 11:38:52 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.
--- a/src/share/vm/utilities/yieldingWorkgroup.hpp Tue Mar 12 11:38:24 2013 +0100 +++ b/src/share/vm/utilities/yieldingWorkgroup.hpp Tue Mar 12 11:38:52 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
--- a/test/TEST.ROOT Tue Mar 12 11:38:24 2013 +0100 +++ b/test/TEST.ROOT Tue Mar 12 11:38:52 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
--- a/test/compiler/5091921/Test6850611.java Tue Mar 12 11:38:24 2013 +0100 +++ b/test/compiler/5091921/Test6850611.java Tue Mar 12 11:38:52 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 {
--- a/test/compiler/5091921/Test6890943.java Tue Mar 12 11:38:24 2013 +0100 +++ b/test/compiler/5091921/Test6890943.java Tue Mar 12 11:38:52 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.*;
--- a/test/compiler/5091921/Test6890943.sh Tue Mar 12 11:38:24 2013 +0100 +++ b/test/compiler/5091921/Test6890943.sh Tue Mar 12 11:38:52 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
--- a/test/compiler/5091921/Test6905845.java Tue Mar 12 11:38:24 2013 +0100 +++ b/test/compiler/5091921/Test6905845.java Tue Mar 12 11:38:52 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 {
--- a/test/compiler/5091921/Test6992759.java Tue Mar 12 11:38:24 2013 +0100 +++ b/test/compiler/5091921/Test6992759.java Tue Mar 12 11:38:52 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 {
--- a/test/compiler/6852078/Test6852078.java Tue Mar 12 11:38:24 2013 +0100 +++ b/test/compiler/6852078/Test6852078.java Tue Mar 12 11:38:52 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); } }
--- a/test/compiler/7009359/Test7009359.java Tue Mar 12 11:38:24 2013 +0100 +++ b/test/compiler/7009359/Test7009359.java Tue Mar 12 11:38:52 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);
--- a/test/compiler/8004741/Test8004741.java Tue Mar 12 11:38:24 2013 +0100 +++ b/test/compiler/8004741/Test8004741.java Tue Mar 12 11:38:52 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); + } };
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/8004867/TestIntAtomicCAS.java Tue Mar 12 11:38:52 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<ARRLEN; i++) { + a1.set(i, -1); + a2.set(i, -1); + } + System.out.println("Warmup"); + for (int i=0; i<ITERS; i++) { + test_ci(a1); + test_vi(a2, 123, -1); + test_cp(a1, a2); + test_2ci(a1, a2); + test_2vi(a1, a2, 123, 103); + test_ci_neg(a1, 123); + test_vi_neg(a2, 123, 103); + test_cp_neg(a1, a2); + test_2ci_neg(a1, a2); + test_2vi_neg(a1, a2, 123, 103); + test_ci_oppos(a1, 123); + test_vi_oppos(a2, 123, 103); + test_cp_oppos(a1, a2); + test_2ci_oppos(a1, a2); + test_2vi_oppos(a1, a2, 123, 103); + test_ci_off(a1, 123); + test_vi_off(a2, 123, 103); + test_cp_off(a1, a2); + test_2ci_off(a1, a2); + test_2vi_off(a1, a2, 123, 103); + test_ci_inv(a1, OFFSET, 123); + test_vi_inv(a2, 123, OFFSET, 103); + test_cp_inv(a1, a2, OFFSET); + test_2ci_inv(a1, a2, OFFSET); + test_2vi_inv(a1, a2, 123, 103, OFFSET); + test_ci_scl(a1, 123); + test_vi_scl(a2, 123, 103); + test_cp_scl(a1, a2); + test_2ci_scl(a1, a2); + test_2vi_scl(a1, a2, 123, 103); + test_cp_alndst(a1, a2); + test_cp_alnsrc(a1, a2); + test_2ci_aln(a1, a2); + test_2vi_aln(a1, a2, 123, 103); + test_cp_unalndst(a1, a2); + test_cp_unalnsrc(a1, a2); + test_2ci_unaln(a1, a2); + test_2vi_unaln(a1, a2, 123, 103); + } + // Initialize + for (int i=0; i<ARRLEN; i++) { + a1.set(i, -1); + a2.set(i, -1); + } + // Test and verify results + System.out.println("Verification"); + int errn = 0; + { + test_ci(a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_ci: a1", i, a1.get(i), -123); + } + test_vi(a2, 123, -1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_vi: a2", i, a2.get(i), 123); + } + test_cp(a1, a2); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_cp: a1", i, a1.get(i), 123); + } + test_2ci(a1, a2); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_2ci: a1", i, a1.get(i), -123); + errn += verify("test_2ci: a2", i, a2.get(i), -103); + } + test_2vi(a1, a2, 123, 103); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_2vi: a1", i, a1.get(i), 123); + errn += verify("test_2vi: a2", i, a2.get(i), 103); + } + // Reset for negative stride + for (int i=0; i<ARRLEN; i++) { + a1.set(i, -1); + a2.set(i, -1); + } + test_ci_neg(a1, -1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_ci_neg: a1", i, a1.get(i), -123); + } + test_vi_neg(a2, 123, -1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_vi_neg: a2", i, a2.get(i), 123); + } + test_cp_neg(a1, a2); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_cp_neg: a1", i, a1.get(i), 123); + } + test_2ci_neg(a1, a2); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_2ci_neg: a1", i, a1.get(i), -123); + errn += verify("test_2ci_neg: a2", i, a2.get(i), -103); + } + test_2vi_neg(a1, a2, 123, 103); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_2vi_neg: a1", i, a1.get(i), 123); + errn += verify("test_2vi_neg: a2", i, a2.get(i), 103); + } + // Reset for opposite stride + for (int i=0; i<ARRLEN; i++) { + a1.set(i, -1); + a2.set(i, -1); + } + test_ci_oppos(a1, -1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_ci_oppos: a1", i, a1.get(i), -123); + } + test_vi_oppos(a2, 123, -1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_vi_oppos: a2", i, a2.get(i), 123); + } + test_cp_oppos(a1, a2); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_cp_oppos: a1", i, a1.get(i), 123); + } + test_2ci_oppos(a1, a2); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_2ci_oppos: a1", i, a1.get(i), -123); + errn += verify("test_2ci_oppos: a2", i, a2.get(i), -103); + } + test_2vi_oppos(a1, a2, 123, 103); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_2vi_oppos: a1", i, a1.get(i), 123); + errn += verify("test_2vi_oppos: a2", i, a2.get(i), 103); + } + // Reset for indexing with offset + for (int i=0; i<ARRLEN; i++) { + a1.set(i, -1); + a2.set(i, -1); + } + test_ci_off(a1, -1); + for (int i=OFFSET; i<ARRLEN; i++) { + errn += verify("test_ci_off: a1", i, a1.get(i), -123); + } + test_vi_off(a2, 123, -1); + for (int i=OFFSET; i<ARRLEN; i++) { + errn += verify("test_vi_off: a2", i, a2.get(i), 123); + } + test_cp_off(a1, a2); + for (int i=OFFSET; i<ARRLEN; i++) { + errn += verify("test_cp_off: a1", i, a1.get(i), 123); + } + test_2ci_off(a1, a2); + for (int i=OFFSET; i<ARRLEN; i++) { + errn += verify("test_2ci_off: a1", i, a1.get(i), -123); + errn += verify("test_2ci_off: a2", i, a2.get(i), -103); + } + test_2vi_off(a1, a2, 123, 103); + for (int i=OFFSET; i<ARRLEN; i++) { + errn += verify("test_2vi_off: a1", i, a1.get(i), 123); + errn += verify("test_2vi_off: a2", i, a2.get(i), 103); + } + for (int i=0; i<OFFSET; i++) { + errn += verify("test_2vi_off: a1", i, a1.get(i), -1); + errn += verify("test_2vi_off: a2", i, a2.get(i), -1); + } + // Reset for indexing with invariant offset + for (int i=0; i<ARRLEN; i++) { + a1.set(i, -1); + a2.set(i, -1); + } + test_ci_inv(a1, OFFSET, -1); + for (int i=OFFSET; i<ARRLEN; i++) { + errn += verify("test_ci_inv: a1", i, a1.get(i), -123); + } + test_vi_inv(a2, 123, OFFSET, -1); + for (int i=OFFSET; i<ARRLEN; i++) { + errn += verify("test_vi_inv: a2", i, a2.get(i), 123); + } + test_cp_inv(a1, a2, OFFSET); + for (int i=OFFSET; i<ARRLEN; i++) { + errn += verify("test_cp_inv: a1", i, a1.get(i), 123); + } + test_2ci_inv(a1, a2, OFFSET); + for (int i=OFFSET; i<ARRLEN; i++) { + errn += verify("test_2ci_inv: a1", i, a1.get(i), -123); + errn += verify("test_2ci_inv: a2", i, a2.get(i), -103); + } + test_2vi_inv(a1, a2, 123, 103, OFFSET); + for (int i=OFFSET; i<ARRLEN; i++) { + errn += verify("test_2vi_inv: a1", i, a1.get(i), 123); + errn += verify("test_2vi_inv: a2", i, a2.get(i), 103); + } + for (int i=0; i<OFFSET; i++) { + errn += verify("test_2vi_inv: a1", i, a1.get(i), -1); + errn += verify("test_2vi_inv: a2", i, a2.get(i), -1); + } + // Reset for indexing with scale + for (int i=0; i<ARRLEN; i++) { + a1.set(i, -1); + a2.set(i, -1); + } + test_ci_scl(a1, -1); + for (int i=0; i<ARRLEN; i++) { + int val = (i%SCALE != 0) ? -1 : -123; + errn += verify("test_ci_scl: a1", i, a1.get(i), val); + } + test_vi_scl(a2, 123, -1); + for (int i=0; i<ARRLEN; i++) { + int val = (i%SCALE != 0) ? -1 : 123; + errn += verify("test_vi_scl: a2", i, a2.get(i), val); + } + test_cp_scl(a1, a2); + for (int i=0; i<ARRLEN; i++) { + int val = (i%SCALE != 0) ? -1 : 123; + errn += verify("test_cp_scl: a1", i, a1.get(i), val); + } + test_2ci_scl(a1, a2); + for (int i=0; i<ARRLEN; i++) { + if (i%SCALE != 0) { + errn += verify("test_2ci_scl: a1", i, a1.get(i), -1); + } else if (i*SCALE < ARRLEN) { + errn += verify("test_2ci_scl: a1", i*SCALE, a1.get(i*SCALE), -123); + } + if (i%SCALE != 0) { + errn += verify("test_2ci_scl: a2", i, a2.get(i), -1); + } else if (i*SCALE < ARRLEN) { + errn += verify("test_2ci_scl: a2", i*SCALE, a2.get(i*SCALE), -103); + } + } + test_2vi_scl(a1, a2, 123, 103); + for (int i=0; i<ARRLEN; i++) { + if (i%SCALE != 0) { + errn += verify("test_2vi_scl: a1", i, a1.get(i), -1); + } else if (i*SCALE < ARRLEN) { + errn += verify("test_2vi_scl: a1", i*SCALE, a1.get(i*SCALE), 123); + } + if (i%SCALE != 0) { + errn += verify("test_2vi_scl: a2", i, a2.get(i), -1); + } else if (i*SCALE < ARRLEN) { + errn += verify("test_2vi_scl: a2", i*SCALE, a2.get(i*SCALE), 103); + } + } + // Reset for 2 arrays with relative aligned offset + for (int i=0; i<ARRLEN; i++) { + a1.set(i, -1); + a2.set(i, -1); + } + test_vi(a2, 123, -1); + test_cp_alndst(a1, a2); + for (int i=0; i<ALIGN_OFF; i++) { + errn += verify("test_cp_alndst: a1", i, a1.get(i), -1); + } + for (int i=ALIGN_OFF; i<ARRLEN; i++) { + errn += verify("test_cp_alndst: a1", i, a1.get(i), 123); + } + for (int i=0; i<ALIGN_OFF; i++) { + a1.set(i, 123); + } + test_vi(a2, -123, 123); + test_cp_alnsrc(a1, a2); + for (int i=0; i<ARRLEN-ALIGN_OFF; i++) { + errn += verify("test_cp_alnsrc: a1", i, a1.get(i), -123); + } + for (int i=ARRLEN-ALIGN_OFF; i<ARRLEN; i++) { + errn += verify("test_cp_alnsrc: a1", i, a1.get(i), 123); + } + for (int i=0; i<ARRLEN; i++) { + a1.set(i, -1); + a2.set(i, -1); + } + test_2ci_aln(a1, a2); + for (int i=0; i<ALIGN_OFF; i++) { + errn += verify("test_2ci_aln: a1", i, a1.get(i), -1); + } + for (int i=ALIGN_OFF; i<ARRLEN; i++) { + errn += verify("test_2ci_aln: a1", i, a1.get(i), -123); + } + for (int i=0; i<ARRLEN-ALIGN_OFF; i++) { + errn += verify("test_2ci_aln: a2", i, a2.get(i), -103); + } + for (int i=ARRLEN-ALIGN_OFF; i<ARRLEN; i++) { + errn += verify("test_2ci_aln: a2", i, a2.get(i), -1); + } + for (int i=0; i<ARRLEN; i++) { + a1.set(i, -1); + a2.set(i, -1); + } + test_2vi_aln(a1, a2, 123, 103); + for (int i=0; i<ARRLEN-ALIGN_OFF; i++) { + errn += verify("test_2vi_aln: a1", i, a1.get(i), 123); + } + for (int i=ARRLEN-ALIGN_OFF; i<ARRLEN; i++) { + errn += verify("test_2vi_aln: a1", i, a1.get(i), -1); + } + for (int i=0; i<ALIGN_OFF; i++) { + errn += verify("test_2vi_aln: a2", i, a2.get(i), -1); + } + for (int i=ALIGN_OFF; i<ARRLEN; i++) { + errn += verify("test_2vi_aln: a2", i, a2.get(i), 103); + } + + // Reset for 2 arrays with relative unaligned offset + for (int i=0; i<ARRLEN; i++) { + a1.set(i, -1); + a2.set(i, -1); + } + test_vi(a2, 123, -1); + test_cp_unalndst(a1, a2); + for (int i=0; i<UNALIGN_OFF; i++) { + errn += verify("test_cp_unalndst: a1", i, a1.get(i), -1); + } + for (int i=UNALIGN_OFF; i<ARRLEN; i++) { + errn += verify("test_cp_unalndst: a1", i, a1.get(i), 123); + } + test_vi(a2, -123, 123); + test_cp_unalnsrc(a1, a2); + for (int i=0; i<ARRLEN-UNALIGN_OFF; i++) { + errn += verify("test_cp_unalnsrc: a1", i, a1.get(i), -123); + } + for (int i=ARRLEN-UNALIGN_OFF; i<ARRLEN; i++) { + errn += verify("test_cp_unalnsrc: a1", i, a1.get(i), 123); + } + for (int i=0; i<ARRLEN; i++) { + a1.set(i, -1); + a2.set(i, -1); + } + test_2ci_unaln(a1, a2); + for (int i=0; i<UNALIGN_OFF; i++) { + errn += verify("test_2ci_unaln: a1", i, a1.get(i), -1); + } + for (int i=UNALIGN_OFF; i<ARRLEN; i++) { + errn += verify("test_2ci_unaln: a1", i, a1.get(i), -123); + } + for (int i=0; i<ARRLEN-UNALIGN_OFF; i++) { + errn += verify("test_2ci_unaln: a2", i, a2.get(i), -103); + } + for (int i=ARRLEN-UNALIGN_OFF; i<ARRLEN; i++) { + errn += verify("test_2ci_unaln: a2", i, a2.get(i), -1); + } + for (int i=0; i<ARRLEN; i++) { + a1.set(i, -1); + a2.set(i, -1); + } + test_2vi_unaln(a1, a2, 123, 103); + for (int i=0; i<ARRLEN-UNALIGN_OFF; i++) { + errn += verify("test_2vi_unaln: a1", i, a1.get(i), 123); + } + for (int i=ARRLEN-UNALIGN_OFF; i<ARRLEN; i++) { + errn += verify("test_2vi_unaln: a1", i, a1.get(i), -1); + } + for (int i=0; i<UNALIGN_OFF; i++) { + errn += verify("test_2vi_unaln: a2", i, a2.get(i), -1); + } + for (int i=UNALIGN_OFF; i<ARRLEN; i++) { + errn += verify("test_2vi_unaln: a2", i, a2.get(i), 103); + } + + // Reset for aligned overlap initialization + for (int i=0; i<ALIGN_OFF; i++) { + a1.set(i, i); + } + for (int i=ALIGN_OFF; i<ARRLEN; i++) { + a1.set(i, -1); + } + test_cp_alndst(a1, a1); + for (int i=0; i<ARRLEN; i++) { + int v = i%ALIGN_OFF; + errn += verify("test_cp_alndst_overlap: a1", i, a1.get(i), v); + } + for (int i=0; i<ALIGN_OFF; i++) { + a1.set((i+ALIGN_OFF), -1); + } + test_cp_alnsrc(a1, a1); + for (int i=0; i<ALIGN_OFF; i++) { + errn += verify("test_cp_alnsrc_overlap: a1", i, a1.get(i), -1); + } + for (int i=ALIGN_OFF; i<ARRLEN; i++) { + int v = i%ALIGN_OFF; + errn += verify("test_cp_alnsrc_overlap: a1", i, a1.get(i), v); + } + for (int i=0; i<ARRLEN; i++) { + a1.set(i, -1); + } + test_2ci_aln(a1, a1); + for (int i=0; i<ARRLEN-ALIGN_OFF; i++) { + errn += verify("test_2ci_aln_overlap: a1", i, a1.get(i), -103); + } + for (int i=ARRLEN-ALIGN_OFF; i<ARRLEN; i++) { + errn += verify("test_2ci_aln_overlap: a1", i, a1.get(i), -123); + } + for (int i=0; i<ARRLEN; i++) { + a1.set(i, -1); + } + test_2vi_aln(a1, a1, 123, 103); + for (int i=0; i<ARRLEN-ALIGN_OFF; i++) { + errn += verify("test_2vi_aln_overlap: a1", i, a1.get(i), 123); + } + for (int i=ARRLEN-ALIGN_OFF; i<ARRLEN; i++) { + errn += verify("test_2vi_aln_overlap: a1", i, a1.get(i), 103); + } + + // Reset for unaligned overlap initialization + for (int i=0; i<UNALIGN_OFF; i++) { + a1.set(i, i); + } + for (int i=UNALIGN_OFF; i<ARRLEN; i++) { + a1.set(i, -1); + } + test_cp_unalndst(a1, a1); + for (int i=0; i<ARRLEN; i++) { + int v = i%UNALIGN_OFF; + errn += verify("test_cp_unalndst_overlap: a1", i, a1.get(i), v); + } + for (int i=0; i<UNALIGN_OFF; i++) { + a1.set((i+UNALIGN_OFF), -1); + } + test_cp_unalnsrc(a1, a1); + for (int i=0; i<UNALIGN_OFF; i++) { + errn += verify("test_cp_unalnsrc_overlap: a1", i, a1.get(i), -1); + } + for (int i=UNALIGN_OFF; i<ARRLEN; i++) { + int v = i%UNALIGN_OFF; + errn += verify("test_cp_unalnsrc_overlap: a1", i, a1.get(i), v); + } + for (int i=0; i<ARRLEN; i++) { + a1.set(i, -1); + } + test_2ci_unaln(a1, a1); + for (int i=0; i<ARRLEN-UNALIGN_OFF; i++) { + errn += verify("test_2ci_unaln_overlap: a1", i, a1.get(i), -103); + } + for (int i=ARRLEN-UNALIGN_OFF; i<ARRLEN; i++) { + errn += verify("test_2ci_unaln_overlap: a1", i, a1.get(i), -123); + } + for (int i=0; i<ARRLEN; i++) { + a1.set(i, -1); + } + test_2vi_unaln(a1, a1, 123, 103); + for (int i=0; i<ARRLEN-UNALIGN_OFF; i++) { + errn += verify("test_2vi_unaln_overlap: a1", i, a1.get(i), 123); + } + for (int i=ARRLEN-UNALIGN_OFF; i<ARRLEN; i++) { + errn += verify("test_2vi_unaln_overlap: a1", i, a1.get(i), 103); + } + + } + + if (errn > 0 || test_only) + return errn; + + // Initialize + for (int i=0; i<ARRLEN; i++) { + a1.set(i, -1); + a2.set(i, -1); + } + System.out.println("Time"); + long start, end; + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_ci(a1); + } + end = System.currentTimeMillis(); + System.out.println("test_ci: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_vi(a2, 123, -1); + } + end = System.currentTimeMillis(); + System.out.println("test_vi: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_cp(a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_cp: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_2ci(a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_2ci: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_2vi(a1, a2, 123, 103); + } + end = System.currentTimeMillis(); + System.out.println("test_2vi: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_ci_neg(a1, 123); + } + end = System.currentTimeMillis(); + System.out.println("test_ci_neg: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_vi_neg(a2, 123, 103); + } + end = System.currentTimeMillis(); + System.out.println("test_vi_neg: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_cp_neg(a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_cp_neg: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_2ci_neg(a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_2ci_neg: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_2vi_neg(a1, a2, 123, 103); + } + end = System.currentTimeMillis(); + System.out.println("test_2vi_neg: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_ci_oppos(a1, 123); + } + end = System.currentTimeMillis(); + System.out.println("test_ci_oppos: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_vi_oppos(a2, 123, 103); + } + end = System.currentTimeMillis(); + System.out.println("test_vi_oppos: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_cp_oppos(a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_cp_oppos: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_2ci_oppos(a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_2ci_oppos: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_2vi_oppos(a1, a2, 123, 103); + } + end = System.currentTimeMillis(); + System.out.println("test_2vi_oppos: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_ci_off(a1, 123); + } + end = System.currentTimeMillis(); + System.out.println("test_ci_off: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_vi_off(a2, 123, 103); + } + end = System.currentTimeMillis(); + System.out.println("test_vi_off: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_cp_off(a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_cp_off: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_2ci_off(a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_2ci_off: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_2vi_off(a1, a2, 123, 103); + } + end = System.currentTimeMillis(); + System.out.println("test_2vi_off: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_ci_inv(a1, OFFSET, 123); + } + end = System.currentTimeMillis(); + System.out.println("test_ci_inv: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_vi_inv(a2, 123, OFFSET, 103); + } + end = System.currentTimeMillis(); + System.out.println("test_vi_inv: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_cp_inv(a1, a2, OFFSET); + } + end = System.currentTimeMillis(); + System.out.println("test_cp_inv: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_2ci_inv(a1, a2, OFFSET); + } + end = System.currentTimeMillis(); + System.out.println("test_2ci_inv: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_2vi_inv(a1, a2, 123, 103, OFFSET); + } + end = System.currentTimeMillis(); + System.out.println("test_2vi_inv: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_ci_scl(a1, 123); + } + end = System.currentTimeMillis(); + System.out.println("test_ci_scl: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_vi_scl(a2, 123, 103); + } + end = System.currentTimeMillis(); + System.out.println("test_vi_scl: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_cp_scl(a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_cp_scl: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_2ci_scl(a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_2ci_scl: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_2vi_scl(a1, a2, 123, 103); + } + end = System.currentTimeMillis(); + System.out.println("test_2vi_scl: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_cp_alndst(a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_cp_alndst: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_cp_alnsrc(a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_cp_alnsrc: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_2ci_aln(a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_2ci_aln: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_2vi_aln(a1, a2, 123, 103); + } + end = System.currentTimeMillis(); + System.out.println("test_2vi_aln: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_cp_unalndst(a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_cp_unalndst: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_cp_unalnsrc(a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_cp_unalnsrc: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_2ci_unaln(a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_2ci_unaln: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_2vi_unaln(a1, a2, 123, 103); + } + end = System.currentTimeMillis(); + System.out.println("test_2vi_unaln: " + (end - start)); + + return errn; + } + + static void test_ci(AtomicIntegerArray a) { + for (int i = 0; i < ARRLEN; i+=1) { + a.compareAndSet(i, -1, -123); + } + } + static void test_vi(AtomicIntegerArray a, int b, int old) { + for (int i = 0; i < ARRLEN; i+=1) { + a.compareAndSet(i, old, b); + } + } + static void test_cp(AtomicIntegerArray a, AtomicIntegerArray b) { + for (int i = 0; i < ARRLEN; i+=1) { + a.compareAndSet(i, -123, b.get(i)); + } + } + static void test_2ci(AtomicIntegerArray a, AtomicIntegerArray b) { + for (int i = 0; i < ARRLEN; i+=1) { + a.compareAndSet(i, 123, -123); + b.compareAndSet(i, 123, -103); + } + } + static void test_2vi(AtomicIntegerArray a, AtomicIntegerArray b, int c, int d) { + for (int i = 0; i < ARRLEN; i+=1) { + a.compareAndSet(i, -123, c); + b.compareAndSet(i, -103, d); + } + } + static void test_ci_neg(AtomicIntegerArray a, int old) { + for (int i = ARRLEN-1; 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; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/8004867/TestIntAtomicOrdered.java Tue Mar 12 11:38:52 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<ARRLEN; i++) { + a1.lazySet(i, -1); + a2.lazySet(i, -1); + } + System.out.println("Warmup"); + for (int i=0; i<ITERS; i++) { + test_ci(a1); + test_vi(a2, 123, -1); + test_cp(a1, a2); + test_2ci(a1, a2); + test_2vi(a1, a2, 123, 103); + test_ci_neg(a1, 123); + test_vi_neg(a2, 123, 103); + test_cp_neg(a1, a2); + test_2ci_neg(a1, a2); + test_2vi_neg(a1, a2, 123, 103); + test_ci_oppos(a1, 123); + test_vi_oppos(a2, 123, 103); + test_cp_oppos(a1, a2); + test_2ci_oppos(a1, a2); + test_2vi_oppos(a1, a2, 123, 103); + test_ci_off(a1, 123); + test_vi_off(a2, 123, 103); + test_cp_off(a1, a2); + test_2ci_off(a1, a2); + test_2vi_off(a1, a2, 123, 103); + test_ci_inv(a1, OFFSET, 123); + test_vi_inv(a2, 123, OFFSET, 103); + test_cp_inv(a1, a2, OFFSET); + test_2ci_inv(a1, a2, OFFSET); + test_2vi_inv(a1, a2, 123, 103, OFFSET); + test_ci_scl(a1, 123); + test_vi_scl(a2, 123, 103); + test_cp_scl(a1, a2); + test_2ci_scl(a1, a2); + test_2vi_scl(a1, a2, 123, 103); + test_cp_alndst(a1, a2); + test_cp_alnsrc(a1, a2); + test_2ci_aln(a1, a2); + test_2vi_aln(a1, a2, 123, 103); + test_cp_unalndst(a1, a2); + test_cp_unalnsrc(a1, a2); + test_2ci_unaln(a1, a2); + test_2vi_unaln(a1, a2, 123, 103); + } + // Initialize + for (int i=0; i<ARRLEN; i++) { + a1.lazySet(i, -1); + a2.lazySet(i, -1); + } + // Test and verify results + System.out.println("Verification"); + int errn = 0; + { + test_ci(a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_ci: a1", i, a1.get(i), -123); + } + test_vi(a2, 123, -1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_vi: a2", i, a2.get(i), 123); + } + test_cp(a1, a2); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_cp: a1", i, a1.get(i), 123); + } + test_2ci(a1, a2); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_2ci: a1", i, a1.get(i), -123); + errn += verify("test_2ci: a2", i, a2.get(i), -103); + } + test_2vi(a1, a2, 123, 103); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_2vi: a1", i, a1.get(i), 123); + errn += verify("test_2vi: a2", i, a2.get(i), 103); + } + // Reset for negative stride + for (int i=0; i<ARRLEN; i++) { + a1.lazySet(i, -1); + a2.lazySet(i, -1); + } + test_ci_neg(a1, -1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_ci_neg: a1", i, a1.get(i), -123); + } + test_vi_neg(a2, 123, -1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_vi_neg: a2", i, a2.get(i), 123); + } + test_cp_neg(a1, a2); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_cp_neg: a1", i, a1.get(i), 123); + } + test_2ci_neg(a1, a2); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_2ci_neg: a1", i, a1.get(i), -123); + errn += verify("test_2ci_neg: a2", i, a2.get(i), -103); + } + test_2vi_neg(a1, a2, 123, 103); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_2vi_neg: a1", i, a1.get(i), 123); + errn += verify("test_2vi_neg: a2", i, a2.get(i), 103); + } + // Reset for opposite stride + for (int i=0; i<ARRLEN; i++) { + a1.lazySet(i, -1); + a2.lazySet(i, -1); + } + test_ci_oppos(a1, -1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_ci_oppos: a1", i, a1.get(i), -123); + } + test_vi_oppos(a2, 123, -1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_vi_oppos: a2", i, a2.get(i), 123); + } + test_cp_oppos(a1, a2); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_cp_oppos: a1", i, a1.get(i), 123); + } + test_2ci_oppos(a1, a2); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_2ci_oppos: a1", i, a1.get(i), -123); + errn += verify("test_2ci_oppos: a2", i, a2.get(i), -103); + } + test_2vi_oppos(a1, a2, 123, 103); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_2vi_oppos: a1", i, a1.get(i), 123); + errn += verify("test_2vi_oppos: a2", i, a2.get(i), 103); + } + // Reset for indexing with offset + for (int i=0; i<ARRLEN; i++) { + a1.lazySet(i, -1); + a2.lazySet(i, -1); + } + test_ci_off(a1, -1); + for (int i=OFFSET; i<ARRLEN; i++) { + errn += verify("test_ci_off: a1", i, a1.get(i), -123); + } + test_vi_off(a2, 123, -1); + for (int i=OFFSET; i<ARRLEN; i++) { + errn += verify("test_vi_off: a2", i, a2.get(i), 123); + } + test_cp_off(a1, a2); + for (int i=OFFSET; i<ARRLEN; i++) { + errn += verify("test_cp_off: a1", i, a1.get(i), 123); + } + test_2ci_off(a1, a2); + for (int i=OFFSET; i<ARRLEN; i++) { + errn += verify("test_2ci_off: a1", i, a1.get(i), -123); + errn += verify("test_2ci_off: a2", i, a2.get(i), -103); + } + test_2vi_off(a1, a2, 123, 103); + for (int i=OFFSET; i<ARRLEN; i++) { + errn += verify("test_2vi_off: a1", i, a1.get(i), 123); + errn += verify("test_2vi_off: a2", i, a2.get(i), 103); + } + for (int i=0; i<OFFSET; i++) { + errn += verify("test_2vi_off: a1", i, a1.get(i), -1); + errn += verify("test_2vi_off: a2", i, a2.get(i), -1); + } + // Reset for indexing with invariant offset + for (int i=0; i<ARRLEN; i++) { + a1.lazySet(i, -1); + a2.lazySet(i, -1); + } + test_ci_inv(a1, OFFSET, -1); + for (int i=OFFSET; i<ARRLEN; i++) { + errn += verify("test_ci_inv: a1", i, a1.get(i), -123); + } + test_vi_inv(a2, 123, OFFSET, -1); + for (int i=OFFSET; i<ARRLEN; i++) { + errn += verify("test_vi_inv: a2", i, a2.get(i), 123); + } + test_cp_inv(a1, a2, OFFSET); + for (int i=OFFSET; i<ARRLEN; i++) { + errn += verify("test_cp_inv: a1", i, a1.get(i), 123); + } + test_2ci_inv(a1, a2, OFFSET); + for (int i=OFFSET; i<ARRLEN; i++) { + errn += verify("test_2ci_inv: a1", i, a1.get(i), -123); + errn += verify("test_2ci_inv: a2", i, a2.get(i), -103); + } + test_2vi_inv(a1, a2, 123, 103, OFFSET); + for (int i=OFFSET; i<ARRLEN; i++) { + errn += verify("test_2vi_inv: a1", i, a1.get(i), 123); + errn += verify("test_2vi_inv: a2", i, a2.get(i), 103); + } + for (int i=0; i<OFFSET; i++) { + errn += verify("test_2vi_inv: a1", i, a1.get(i), -1); + errn += verify("test_2vi_inv: a2", i, a2.get(i), -1); + } + // Reset for indexing with scale + for (int i=0; i<ARRLEN; i++) { + a1.lazySet(i, -1); + a2.lazySet(i, -1); + } + test_ci_scl(a1, -1); + for (int i=0; i<ARRLEN; i++) { + int val = (i%SCALE != 0) ? -1 : -123; + errn += verify("test_ci_scl: a1", i, a1.get(i), val); + } + test_vi_scl(a2, 123, -1); + for (int i=0; i<ARRLEN; i++) { + int val = (i%SCALE != 0) ? -1 : 123; + errn += verify("test_vi_scl: a2", i, a2.get(i), val); + } + test_cp_scl(a1, a2); + for (int i=0; i<ARRLEN; i++) { + int val = (i%SCALE != 0) ? -1 : 123; + errn += verify("test_cp_scl: a1", i, a1.get(i), val); + } + test_2ci_scl(a1, a2); + for (int i=0; i<ARRLEN; i++) { + if (i%SCALE != 0) { + errn += verify("test_2ci_scl: a1", i, a1.get(i), -1); + } else if (i*SCALE < ARRLEN) { + errn += verify("test_2ci_scl: a1", i*SCALE, a1.get(i*SCALE), -123); + } + if (i%SCALE != 0) { + errn += verify("test_2ci_scl: a2", i, a2.get(i), -1); + } else if (i*SCALE < ARRLEN) { + errn += verify("test_2ci_scl: a2", i*SCALE, a2.get(i*SCALE), -103); + } + } + test_2vi_scl(a1, a2, 123, 103); + for (int i=0; i<ARRLEN; i++) { + if (i%SCALE != 0) { + errn += verify("test_2vi_scl: a1", i, a1.get(i), -1); + } else if (i*SCALE < ARRLEN) { + errn += verify("test_2vi_scl: a1", i*SCALE, a1.get(i*SCALE), 123); + } + if (i%SCALE != 0) { + errn += verify("test_2vi_scl: a2", i, a2.get(i), -1); + } else if (i*SCALE < ARRLEN) { + errn += verify("test_2vi_scl: a2", i*SCALE, a2.get(i*SCALE), 103); + } + } + // Reset for 2 arrays with relative aligned offset + for (int i=0; i<ARRLEN; i++) { + a1.lazySet(i, -1); + a2.lazySet(i, -1); + } + test_vi(a2, 123, -1); + test_cp_alndst(a1, a2); + for (int i=0; i<ALIGN_OFF; i++) { + errn += verify("test_cp_alndst: a1", i, a1.get(i), -1); + } + for (int i=ALIGN_OFF; i<ARRLEN; i++) { + errn += verify("test_cp_alndst: a1", i, a1.get(i), 123); + } + for (int i=0; i<ALIGN_OFF; i++) { + a1.lazySet(i, 123); + } + test_vi(a2, -123, 123); + test_cp_alnsrc(a1, a2); + for (int i=0; i<ARRLEN-ALIGN_OFF; i++) { + errn += verify("test_cp_alnsrc: a1", i, a1.get(i), -123); + } + for (int i=ARRLEN-ALIGN_OFF; i<ARRLEN; i++) { + errn += verify("test_cp_alnsrc: a1", i, a1.get(i), 123); + } + for (int i=0; i<ARRLEN; i++) { + a1.lazySet(i, -1); + a2.lazySet(i, -1); + } + test_2ci_aln(a1, a2); + for (int i=0; i<ALIGN_OFF; i++) { + errn += verify("test_2ci_aln: a1", i, a1.get(i), -1); + } + for (int i=ALIGN_OFF; i<ARRLEN; i++) { + errn += verify("test_2ci_aln: a1", i, a1.get(i), -123); + } + for (int i=0; i<ARRLEN-ALIGN_OFF; i++) { + errn += verify("test_2ci_aln: a2", i, a2.get(i), -103); + } + for (int i=ARRLEN-ALIGN_OFF; i<ARRLEN; i++) { + errn += verify("test_2ci_aln: a2", i, a2.get(i), -1); + } + for (int i=0; i<ARRLEN; i++) { + a1.lazySet(i, -1); + a2.lazySet(i, -1); + } + test_2vi_aln(a1, a2, 123, 103); + for (int i=0; i<ARRLEN-ALIGN_OFF; i++) { + errn += verify("test_2vi_aln: a1", i, a1.get(i), 123); + } + for (int i=ARRLEN-ALIGN_OFF; i<ARRLEN; i++) { + errn += verify("test_2vi_aln: a1", i, a1.get(i), -1); + } + for (int i=0; i<ALIGN_OFF; i++) { + errn += verify("test_2vi_aln: a2", i, a2.get(i), -1); + } + for (int i=ALIGN_OFF; i<ARRLEN; i++) { + errn += verify("test_2vi_aln: a2", i, a2.get(i), 103); + } + + // Reset for 2 arrays with relative unaligned offset + for (int i=0; i<ARRLEN; i++) { + a1.lazySet(i, -1); + a2.lazySet(i, -1); + } + test_vi(a2, 123, -1); + test_cp_unalndst(a1, a2); + for (int i=0; i<UNALIGN_OFF; i++) { + errn += verify("test_cp_unalndst: a1", i, a1.get(i), -1); + } + for (int i=UNALIGN_OFF; i<ARRLEN; i++) { + errn += verify("test_cp_unalndst: a1", i, a1.get(i), 123); + } + test_vi(a2, -123, 123); + test_cp_unalnsrc(a1, a2); + for (int i=0; i<ARRLEN-UNALIGN_OFF; i++) { + errn += verify("test_cp_unalnsrc: a1", i, a1.get(i), -123); + } + for (int i=ARRLEN-UNALIGN_OFF; i<ARRLEN; i++) { + errn += verify("test_cp_unalnsrc: a1", i, a1.get(i), 123); + } + for (int i=0; i<ARRLEN; i++) { + a1.lazySet(i, -1); + a2.lazySet(i, -1); + } + test_2ci_unaln(a1, a2); + for (int i=0; i<UNALIGN_OFF; i++) { + errn += verify("test_2ci_unaln: a1", i, a1.get(i), -1); + } + for (int i=UNALIGN_OFF; i<ARRLEN; i++) { + errn += verify("test_2ci_unaln: a1", i, a1.get(i), -123); + } + for (int i=0; i<ARRLEN-UNALIGN_OFF; i++) { + errn += verify("test_2ci_unaln: a2", i, a2.get(i), -103); + } + for (int i=ARRLEN-UNALIGN_OFF; i<ARRLEN; i++) { + errn += verify("test_2ci_unaln: a2", i, a2.get(i), -1); + } + for (int i=0; i<ARRLEN; i++) { + a1.lazySet(i, -1); + a2.lazySet(i, -1); + } + test_2vi_unaln(a1, a2, 123, 103); + for (int i=0; i<ARRLEN-UNALIGN_OFF; i++) { + errn += verify("test_2vi_unaln: a1", i, a1.get(i), 123); + } + for (int i=ARRLEN-UNALIGN_OFF; i<ARRLEN; i++) { + errn += verify("test_2vi_unaln: a1", i, a1.get(i), -1); + } + for (int i=0; i<UNALIGN_OFF; i++) { + errn += verify("test_2vi_unaln: a2", i, a2.get(i), -1); + } + for (int i=UNALIGN_OFF; i<ARRLEN; i++) { + errn += verify("test_2vi_unaln: a2", i, a2.get(i), 103); + } + + // Reset for aligned overlap initialization + for (int i=0; i<ALIGN_OFF; i++) { + a1.lazySet(i, i); + } + for (int i=ALIGN_OFF; i<ARRLEN; i++) { + a1.lazySet(i, -1); + } + test_cp_alndst(a1, a1); + for (int i=0; i<ARRLEN; i++) { + int v = i%ALIGN_OFF; + errn += verify("test_cp_alndst_overlap: a1", i, a1.get(i), v); + } + for (int i=0; i<ALIGN_OFF; i++) { + a1.lazySet((i+ALIGN_OFF), -1); + } + test_cp_alnsrc(a1, a1); + for (int i=0; i<ALIGN_OFF; i++) { + errn += verify("test_cp_alnsrc_overlap: a1", i, a1.get(i), -1); + } + for (int i=ALIGN_OFF; i<ARRLEN; i++) { + int v = i%ALIGN_OFF; + errn += verify("test_cp_alnsrc_overlap: a1", i, a1.get(i), v); + } + for (int i=0; i<ARRLEN; i++) { + a1.lazySet(i, -1); + } + test_2ci_aln(a1, a1); + for (int i=0; i<ARRLEN-ALIGN_OFF; i++) { + errn += verify("test_2ci_aln_overlap: a1", i, a1.get(i), -103); + } + for (int i=ARRLEN-ALIGN_OFF; i<ARRLEN; i++) { + errn += verify("test_2ci_aln_overlap: a1", i, a1.get(i), -123); + } + for (int i=0; i<ARRLEN; i++) { + a1.lazySet(i, -1); + } + test_2vi_aln(a1, a1, 123, 103); + for (int i=0; i<ARRLEN-ALIGN_OFF; i++) { + errn += verify("test_2vi_aln_overlap: a1", i, a1.get(i), 123); + } + for (int i=ARRLEN-ALIGN_OFF; i<ARRLEN; i++) { + errn += verify("test_2vi_aln_overlap: a1", i, a1.get(i), 103); + } + + // Reset for unaligned overlap initialization + for (int i=0; i<UNALIGN_OFF; i++) { + a1.lazySet(i, i); + } + for (int i=UNALIGN_OFF; i<ARRLEN; i++) { + a1.lazySet(i, -1); + } + test_cp_unalndst(a1, a1); + for (int i=0; i<ARRLEN; i++) { + int v = i%UNALIGN_OFF; + errn += verify("test_cp_unalndst_overlap: a1", i, a1.get(i), v); + } + for (int i=0; i<UNALIGN_OFF; i++) { + a1.lazySet((i+UNALIGN_OFF), -1); + } + test_cp_unalnsrc(a1, a1); + for (int i=0; i<UNALIGN_OFF; i++) { + errn += verify("test_cp_unalnsrc_overlap: a1", i, a1.get(i), -1); + } + for (int i=UNALIGN_OFF; i<ARRLEN; i++) { + int v = i%UNALIGN_OFF; + errn += verify("test_cp_unalnsrc_overlap: a1", i, a1.get(i), v); + } + for (int i=0; i<ARRLEN; i++) { + a1.lazySet(i, -1); + } + test_2ci_unaln(a1, a1); + for (int i=0; i<ARRLEN-UNALIGN_OFF; i++) { + errn += verify("test_2ci_unaln_overlap: a1", i, a1.get(i), -103); + } + for (int i=ARRLEN-UNALIGN_OFF; i<ARRLEN; i++) { + errn += verify("test_2ci_unaln_overlap: a1", i, a1.get(i), -123); + } + for (int i=0; i<ARRLEN; i++) { + a1.lazySet(i, -1); + } + test_2vi_unaln(a1, a1, 123, 103); + for (int i=0; i<ARRLEN-UNALIGN_OFF; i++) { + errn += verify("test_2vi_unaln_overlap: a1", i, a1.get(i), 123); + } + for (int i=ARRLEN-UNALIGN_OFF; i<ARRLEN; i++) { + errn += verify("test_2vi_unaln_overlap: a1", i, a1.get(i), 103); + } + + } + + if (errn > 0 || test_only) + return errn; + + // Initialize + for (int i=0; i<ARRLEN; i++) { + a1.lazySet(i, -1); + a2.lazySet(i, -1); + } + System.out.println("Time"); + long start, end; + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_ci(a1); + } + end = System.currentTimeMillis(); + System.out.println("test_ci: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_vi(a2, 123, -1); + } + end = System.currentTimeMillis(); + System.out.println("test_vi: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_cp(a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_cp: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_2ci(a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_2ci: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_2vi(a1, a2, 123, 103); + } + end = System.currentTimeMillis(); + System.out.println("test_2vi: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_ci_neg(a1, 123); + } + end = System.currentTimeMillis(); + System.out.println("test_ci_neg: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_vi_neg(a2, 123, 103); + } + end = System.currentTimeMillis(); + System.out.println("test_vi_neg: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_cp_neg(a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_cp_neg: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_2ci_neg(a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_2ci_neg: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_2vi_neg(a1, a2, 123, 103); + } + end = System.currentTimeMillis(); + System.out.println("test_2vi_neg: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_ci_oppos(a1, 123); + } + end = System.currentTimeMillis(); + System.out.println("test_ci_oppos: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_vi_oppos(a2, 123, 103); + } + end = System.currentTimeMillis(); + System.out.println("test_vi_oppos: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_cp_oppos(a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_cp_oppos: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_2ci_oppos(a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_2ci_oppos: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_2vi_oppos(a1, a2, 123, 103); + } + end = System.currentTimeMillis(); + System.out.println("test_2vi_oppos: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_ci_off(a1, 123); + } + end = System.currentTimeMillis(); + System.out.println("test_ci_off: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_vi_off(a2, 123, 103); + } + end = System.currentTimeMillis(); + System.out.println("test_vi_off: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_cp_off(a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_cp_off: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_2ci_off(a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_2ci_off: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_2vi_off(a1, a2, 123, 103); + } + end = System.currentTimeMillis(); + System.out.println("test_2vi_off: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_ci_inv(a1, OFFSET, 123); + } + end = System.currentTimeMillis(); + System.out.println("test_ci_inv: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_vi_inv(a2, 123, OFFSET, 103); + } + end = System.currentTimeMillis(); + System.out.println("test_vi_inv: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_cp_inv(a1, a2, OFFSET); + } + end = System.currentTimeMillis(); + System.out.println("test_cp_inv: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_2ci_inv(a1, a2, OFFSET); + } + end = System.currentTimeMillis(); + System.out.println("test_2ci_inv: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_2vi_inv(a1, a2, 123, 103, OFFSET); + } + end = System.currentTimeMillis(); + System.out.println("test_2vi_inv: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_ci_scl(a1, 123); + } + end = System.currentTimeMillis(); + System.out.println("test_ci_scl: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_vi_scl(a2, 123, 103); + } + end = System.currentTimeMillis(); + System.out.println("test_vi_scl: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_cp_scl(a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_cp_scl: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_2ci_scl(a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_2ci_scl: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_2vi_scl(a1, a2, 123, 103); + } + end = System.currentTimeMillis(); + System.out.println("test_2vi_scl: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_cp_alndst(a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_cp_alndst: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_cp_alnsrc(a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_cp_alnsrc: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_2ci_aln(a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_2ci_aln: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_2vi_aln(a1, a2, 123, 103); + } + end = System.currentTimeMillis(); + System.out.println("test_2vi_aln: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_cp_unalndst(a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_cp_unalndst: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_cp_unalnsrc(a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_cp_unalnsrc: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_2ci_unaln(a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_2ci_unaln: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_2vi_unaln(a1, a2, 123, 103); + } + end = System.currentTimeMillis(); + System.out.println("test_2vi_unaln: " + (end - start)); + + return errn; + } + + static void test_ci(AtomicIntegerArray a) { + for (int i = 0; i < ARRLEN; i+=1) { + a.lazySet(i, -123); + } + } + static void test_vi(AtomicIntegerArray a, int b, int old) { + for (int i = 0; i < ARRLEN; i+=1) { + a.lazySet(i, b); + } + } + static void test_cp(AtomicIntegerArray a, AtomicIntegerArray b) { + for (int i = 0; i < ARRLEN; i+=1) { + a.lazySet(i, b.get(i)); + } + } + static void test_2ci(AtomicIntegerArray a, AtomicIntegerArray b) { + for (int i = 0; i < ARRLEN; i+=1) { + a.lazySet(i, -123); + b.lazySet(i, -103); + } + } + static void test_2vi(AtomicIntegerArray a, AtomicIntegerArray b, int c, int d) { + for (int i = 0; i < ARRLEN; i+=1) { + a.lazySet(i, c); + b.lazySet(i, d); + } + } + static void test_ci_neg(AtomicIntegerArray a, int old) { + for (int i = ARRLEN-1; 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; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/8004867/TestIntAtomicVolatile.java Tue Mar 12 11:38:52 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<ARRLEN; i++) { + a1.set(i, -1); + a2.set(i, -1); + } + System.out.println("Warmup"); + for (int i=0; i<ITERS; i++) { + test_ci(a1); + test_vi(a2, 123, -1); + test_cp(a1, a2); + test_2ci(a1, a2); + test_2vi(a1, a2, 123, 103); + test_ci_neg(a1, 123); + test_vi_neg(a2, 123, 103); + test_cp_neg(a1, a2); + test_2ci_neg(a1, a2); + test_2vi_neg(a1, a2, 123, 103); + test_ci_oppos(a1, 123); + test_vi_oppos(a2, 123, 103); + test_cp_oppos(a1, a2); + test_2ci_oppos(a1, a2); + test_2vi_oppos(a1, a2, 123, 103); + test_ci_off(a1, 123); + test_vi_off(a2, 123, 103); + test_cp_off(a1, a2); + test_2ci_off(a1, a2); + test_2vi_off(a1, a2, 123, 103); + test_ci_inv(a1, OFFSET, 123); + test_vi_inv(a2, 123, OFFSET, 103); + test_cp_inv(a1, a2, OFFSET); + test_2ci_inv(a1, a2, OFFSET); + test_2vi_inv(a1, a2, 123, 103, OFFSET); + test_ci_scl(a1, 123); + test_vi_scl(a2, 123, 103); + test_cp_scl(a1, a2); + test_2ci_scl(a1, a2); + test_2vi_scl(a1, a2, 123, 103); + test_cp_alndst(a1, a2); + test_cp_alnsrc(a1, a2); + test_2ci_aln(a1, a2); + test_2vi_aln(a1, a2, 123, 103); + test_cp_unalndst(a1, a2); + test_cp_unalnsrc(a1, a2); + test_2ci_unaln(a1, a2); + test_2vi_unaln(a1, a2, 123, 103); + } + // Initialize + for (int i=0; i<ARRLEN; i++) { + a1.set(i, -1); + a2.set(i, -1); + } + // Test and verify results + System.out.println("Verification"); + int errn = 0; + { + test_ci(a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_ci: a1", i, a1.get(i), -123); + } + test_vi(a2, 123, -1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_vi: a2", i, a2.get(i), 123); + } + test_cp(a1, a2); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_cp: a1", i, a1.get(i), 123); + } + test_2ci(a1, a2); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_2ci: a1", i, a1.get(i), -123); + errn += verify("test_2ci: a2", i, a2.get(i), -103); + } + test_2vi(a1, a2, 123, 103); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_2vi: a1", i, a1.get(i), 123); + errn += verify("test_2vi: a2", i, a2.get(i), 103); + } + // Reset for negative stride + for (int i=0; i<ARRLEN; i++) { + a1.set(i, -1); + a2.set(i, -1); + } + test_ci_neg(a1, -1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_ci_neg: a1", i, a1.get(i), -123); + } + test_vi_neg(a2, 123, -1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_vi_neg: a2", i, a2.get(i), 123); + } + test_cp_neg(a1, a2); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_cp_neg: a1", i, a1.get(i), 123); + } + test_2ci_neg(a1, a2); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_2ci_neg: a1", i, a1.get(i), -123); + errn += verify("test_2ci_neg: a2", i, a2.get(i), -103); + } + test_2vi_neg(a1, a2, 123, 103); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_2vi_neg: a1", i, a1.get(i), 123); + errn += verify("test_2vi_neg: a2", i, a2.get(i), 103); + } + // Reset for opposite stride + for (int i=0; i<ARRLEN; i++) { + a1.set(i, -1); + a2.set(i, -1); + } + test_ci_oppos(a1, -1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_ci_oppos: a1", i, a1.get(i), -123); + } + test_vi_oppos(a2, 123, -1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_vi_oppos: a2", i, a2.get(i), 123); + } + test_cp_oppos(a1, a2); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_cp_oppos: a1", i, a1.get(i), 123); + } + test_2ci_oppos(a1, a2); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_2ci_oppos: a1", i, a1.get(i), -123); + errn += verify("test_2ci_oppos: a2", i, a2.get(i), -103); + } + test_2vi_oppos(a1, a2, 123, 103); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_2vi_oppos: a1", i, a1.get(i), 123); + errn += verify("test_2vi_oppos: a2", i, a2.get(i), 103); + } + // Reset for indexing with offset + for (int i=0; i<ARRLEN; i++) { + a1.set(i, -1); + a2.set(i, -1); + } + test_ci_off(a1, -1); + for (int i=OFFSET; i<ARRLEN; i++) { + errn += verify("test_ci_off: a1", i, a1.get(i), -123); + } + test_vi_off(a2, 123, -1); + for (int i=OFFSET; i<ARRLEN; i++) { + errn += verify("test_vi_off: a2", i, a2.get(i), 123); + } + test_cp_off(a1, a2); + for (int i=OFFSET; i<ARRLEN; i++) { + errn += verify("test_cp_off: a1", i, a1.get(i), 123); + } + test_2ci_off(a1, a2); + for (int i=OFFSET; i<ARRLEN; i++) { + errn += verify("test_2ci_off: a1", i, a1.get(i), -123); + errn += verify("test_2ci_off: a2", i, a2.get(i), -103); + } + test_2vi_off(a1, a2, 123, 103); + for (int i=OFFSET; i<ARRLEN; i++) { + errn += verify("test_2vi_off: a1", i, a1.get(i), 123); + errn += verify("test_2vi_off: a2", i, a2.get(i), 103); + } + for (int i=0; i<OFFSET; i++) { + errn += verify("test_2vi_off: a1", i, a1.get(i), -1); + errn += verify("test_2vi_off: a2", i, a2.get(i), -1); + } + // Reset for indexing with invariant offset + for (int i=0; i<ARRLEN; i++) { + a1.set(i, -1); + a2.set(i, -1); + } + test_ci_inv(a1, OFFSET, -1); + for (int i=OFFSET; i<ARRLEN; i++) { + errn += verify("test_ci_inv: a1", i, a1.get(i), -123); + } + test_vi_inv(a2, 123, OFFSET, -1); + for (int i=OFFSET; i<ARRLEN; i++) { + errn += verify("test_vi_inv: a2", i, a2.get(i), 123); + } + test_cp_inv(a1, a2, OFFSET); + for (int i=OFFSET; i<ARRLEN; i++) { + errn += verify("test_cp_inv: a1", i, a1.get(i), 123); + } + test_2ci_inv(a1, a2, OFFSET); + for (int i=OFFSET; i<ARRLEN; i++) { + errn += verify("test_2ci_inv: a1", i, a1.get(i), -123); + errn += verify("test_2ci_inv: a2", i, a2.get(i), -103); + } + test_2vi_inv(a1, a2, 123, 103, OFFSET); + for (int i=OFFSET; i<ARRLEN; i++) { + errn += verify("test_2vi_inv: a1", i, a1.get(i), 123); + errn += verify("test_2vi_inv: a2", i, a2.get(i), 103); + } + for (int i=0; i<OFFSET; i++) { + errn += verify("test_2vi_inv: a1", i, a1.get(i), -1); + errn += verify("test_2vi_inv: a2", i, a2.get(i), -1); + } + // Reset for indexing with scale + for (int i=0; i<ARRLEN; i++) { + a1.set(i, -1); + a2.set(i, -1); + } + test_ci_scl(a1, -1); + for (int i=0; i<ARRLEN; i++) { + int val = (i%SCALE != 0) ? -1 : -123; + errn += verify("test_ci_scl: a1", i, a1.get(i), val); + } + test_vi_scl(a2, 123, -1); + for (int i=0; i<ARRLEN; i++) { + int val = (i%SCALE != 0) ? -1 : 123; + errn += verify("test_vi_scl: a2", i, a2.get(i), val); + } + test_cp_scl(a1, a2); + for (int i=0; i<ARRLEN; i++) { + int val = (i%SCALE != 0) ? -1 : 123; + errn += verify("test_cp_scl: a1", i, a1.get(i), val); + } + test_2ci_scl(a1, a2); + for (int i=0; i<ARRLEN; i++) { + if (i%SCALE != 0) { + errn += verify("test_2ci_scl: a1", i, a1.get(i), -1); + } else if (i*SCALE < ARRLEN) { + errn += verify("test_2ci_scl: a1", i*SCALE, a1.get(i*SCALE), -123); + } + if (i%SCALE != 0) { + errn += verify("test_2ci_scl: a2", i, a2.get(i), -1); + } else if (i*SCALE < ARRLEN) { + errn += verify("test_2ci_scl: a2", i*SCALE, a2.get(i*SCALE), -103); + } + } + test_2vi_scl(a1, a2, 123, 103); + for (int i=0; i<ARRLEN; i++) { + if (i%SCALE != 0) { + errn += verify("test_2vi_scl: a1", i, a1.get(i), -1); + } else if (i*SCALE < ARRLEN) { + errn += verify("test_2vi_scl: a1", i*SCALE, a1.get(i*SCALE), 123); + } + if (i%SCALE != 0) { + errn += verify("test_2vi_scl: a2", i, a2.get(i), -1); + } else if (i*SCALE < ARRLEN) { + errn += verify("test_2vi_scl: a2", i*SCALE, a2.get(i*SCALE), 103); + } + } + // Reset for 2 arrays with relative aligned offset + for (int i=0; i<ARRLEN; i++) { + a1.set(i, -1); + a2.set(i, -1); + } + test_vi(a2, 123, -1); + test_cp_alndst(a1, a2); + for (int i=0; i<ALIGN_OFF; i++) { + errn += verify("test_cp_alndst: a1", i, a1.get(i), -1); + } + for (int i=ALIGN_OFF; i<ARRLEN; i++) { + errn += verify("test_cp_alndst: a1", i, a1.get(i), 123); + } + for (int i=0; i<ALIGN_OFF; i++) { + a1.set(i, 123); + } + test_vi(a2, -123, 123); + test_cp_alnsrc(a1, a2); + for (int i=0; i<ARRLEN-ALIGN_OFF; i++) { + errn += verify("test_cp_alnsrc: a1", i, a1.get(i), -123); + } + for (int i=ARRLEN-ALIGN_OFF; i<ARRLEN; i++) { + errn += verify("test_cp_alnsrc: a1", i, a1.get(i), 123); + } + for (int i=0; i<ARRLEN; i++) { + a1.set(i, -1); + a2.set(i, -1); + } + test_2ci_aln(a1, a2); + for (int i=0; i<ALIGN_OFF; i++) { + errn += verify("test_2ci_aln: a1", i, a1.get(i), -1); + } + for (int i=ALIGN_OFF; i<ARRLEN; i++) { + errn += verify("test_2ci_aln: a1", i, a1.get(i), -123); + } + for (int i=0; i<ARRLEN-ALIGN_OFF; i++) { + errn += verify("test_2ci_aln: a2", i, a2.get(i), -103); + } + for (int i=ARRLEN-ALIGN_OFF; i<ARRLEN; i++) { + errn += verify("test_2ci_aln: a2", i, a2.get(i), -1); + } + for (int i=0; i<ARRLEN; i++) { + a1.set(i, -1); + a2.set(i, -1); + } + test_2vi_aln(a1, a2, 123, 103); + for (int i=0; i<ARRLEN-ALIGN_OFF; i++) { + errn += verify("test_2vi_aln: a1", i, a1.get(i), 123); + } + for (int i=ARRLEN-ALIGN_OFF; i<ARRLEN; i++) { + errn += verify("test_2vi_aln: a1", i, a1.get(i), -1); + } + for (int i=0; i<ALIGN_OFF; i++) { + errn += verify("test_2vi_aln: a2", i, a2.get(i), -1); + } + for (int i=ALIGN_OFF; i<ARRLEN; i++) { + errn += verify("test_2vi_aln: a2", i, a2.get(i), 103); + } + + // Reset for 2 arrays with relative unaligned offset + for (int i=0; i<ARRLEN; i++) { + a1.set(i, -1); + a2.set(i, -1); + } + test_vi(a2, 123, -1); + test_cp_unalndst(a1, a2); + for (int i=0; i<UNALIGN_OFF; i++) { + errn += verify("test_cp_unalndst: a1", i, a1.get(i), -1); + } + for (int i=UNALIGN_OFF; i<ARRLEN; i++) { + errn += verify("test_cp_unalndst: a1", i, a1.get(i), 123); + } + test_vi(a2, -123, 123); + test_cp_unalnsrc(a1, a2); + for (int i=0; i<ARRLEN-UNALIGN_OFF; i++) { + errn += verify("test_cp_unalnsrc: a1", i, a1.get(i), -123); + } + for (int i=ARRLEN-UNALIGN_OFF; i<ARRLEN; i++) { + errn += verify("test_cp_unalnsrc: a1", i, a1.get(i), 123); + } + for (int i=0; i<ARRLEN; i++) { + a1.set(i, -1); + a2.set(i, -1); + } + test_2ci_unaln(a1, a2); + for (int i=0; i<UNALIGN_OFF; i++) { + errn += verify("test_2ci_unaln: a1", i, a1.get(i), -1); + } + for (int i=UNALIGN_OFF; i<ARRLEN; i++) { + errn += verify("test_2ci_unaln: a1", i, a1.get(i), -123); + } + for (int i=0; i<ARRLEN-UNALIGN_OFF; i++) { + errn += verify("test_2ci_unaln: a2", i, a2.get(i), -103); + } + for (int i=ARRLEN-UNALIGN_OFF; i<ARRLEN; i++) { + errn += verify("test_2ci_unaln: a2", i, a2.get(i), -1); + } + for (int i=0; i<ARRLEN; i++) { + a1.set(i, -1); + a2.set(i, -1); + } + test_2vi_unaln(a1, a2, 123, 103); + for (int i=0; i<ARRLEN-UNALIGN_OFF; i++) { + errn += verify("test_2vi_unaln: a1", i, a1.get(i), 123); + } + for (int i=ARRLEN-UNALIGN_OFF; i<ARRLEN; i++) { + errn += verify("test_2vi_unaln: a1", i, a1.get(i), -1); + } + for (int i=0; i<UNALIGN_OFF; i++) { + errn += verify("test_2vi_unaln: a2", i, a2.get(i), -1); + } + for (int i=UNALIGN_OFF; i<ARRLEN; i++) { + errn += verify("test_2vi_unaln: a2", i, a2.get(i), 103); + } + + // Reset for aligned overlap initialization + for (int i=0; i<ALIGN_OFF; i++) { + a1.set(i, i); + } + for (int i=ALIGN_OFF; i<ARRLEN; i++) { + a1.set(i, -1); + } + test_cp_alndst(a1, a1); + for (int i=0; i<ARRLEN; i++) { + int v = i%ALIGN_OFF; + errn += verify("test_cp_alndst_overlap: a1", i, a1.get(i), v); + } + for (int i=0; i<ALIGN_OFF; i++) { + a1.set((i+ALIGN_OFF), -1); + } + test_cp_alnsrc(a1, a1); + for (int i=0; i<ALIGN_OFF; i++) { + errn += verify("test_cp_alnsrc_overlap: a1", i, a1.get(i), -1); + } + for (int i=ALIGN_OFF; i<ARRLEN; i++) { + int v = i%ALIGN_OFF; + errn += verify("test_cp_alnsrc_overlap: a1", i, a1.get(i), v); + } + for (int i=0; i<ARRLEN; i++) { + a1.set(i, -1); + } + test_2ci_aln(a1, a1); + for (int i=0; i<ARRLEN-ALIGN_OFF; i++) { + errn += verify("test_2ci_aln_overlap: a1", i, a1.get(i), -103); + } + for (int i=ARRLEN-ALIGN_OFF; i<ARRLEN; i++) { + errn += verify("test_2ci_aln_overlap: a1", i, a1.get(i), -123); + } + for (int i=0; i<ARRLEN; i++) { + a1.set(i, -1); + } + test_2vi_aln(a1, a1, 123, 103); + for (int i=0; i<ARRLEN-ALIGN_OFF; i++) { + errn += verify("test_2vi_aln_overlap: a1", i, a1.get(i), 123); + } + for (int i=ARRLEN-ALIGN_OFF; i<ARRLEN; i++) { + errn += verify("test_2vi_aln_overlap: a1", i, a1.get(i), 103); + } + + // Reset for unaligned overlap initialization + for (int i=0; i<UNALIGN_OFF; i++) { + a1.set(i, i); + } + for (int i=UNALIGN_OFF; i<ARRLEN; i++) { + a1.set(i, -1); + } + test_cp_unalndst(a1, a1); + for (int i=0; i<ARRLEN; i++) { + int v = i%UNALIGN_OFF; + errn += verify("test_cp_unalndst_overlap: a1", i, a1.get(i), v); + } + for (int i=0; i<UNALIGN_OFF; i++) { + a1.set((i+UNALIGN_OFF), -1); + } + test_cp_unalnsrc(a1, a1); + for (int i=0; i<UNALIGN_OFF; i++) { + errn += verify("test_cp_unalnsrc_overlap: a1", i, a1.get(i), -1); + } + for (int i=UNALIGN_OFF; i<ARRLEN; i++) { + int v = i%UNALIGN_OFF; + errn += verify("test_cp_unalnsrc_overlap: a1", i, a1.get(i), v); + } + for (int i=0; i<ARRLEN; i++) { + a1.set(i, -1); + } + test_2ci_unaln(a1, a1); + for (int i=0; i<ARRLEN-UNALIGN_OFF; i++) { + errn += verify("test_2ci_unaln_overlap: a1", i, a1.get(i), -103); + } + for (int i=ARRLEN-UNALIGN_OFF; i<ARRLEN; i++) { + errn += verify("test_2ci_unaln_overlap: a1", i, a1.get(i), -123); + } + for (int i=0; i<ARRLEN; i++) { + a1.set(i, -1); + } + test_2vi_unaln(a1, a1, 123, 103); + for (int i=0; i<ARRLEN-UNALIGN_OFF; i++) { + errn += verify("test_2vi_unaln_overlap: a1", i, a1.get(i), 123); + } + for (int i=ARRLEN-UNALIGN_OFF; i<ARRLEN; i++) { + errn += verify("test_2vi_unaln_overlap: a1", i, a1.get(i), 103); + } + + } + + if (errn > 0 || test_only) + return errn; + + // Initialize + for (int i=0; i<ARRLEN; i++) { + a1.set(i, -1); + a2.set(i, -1); + } + System.out.println("Time"); + long start, end; + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_ci(a1); + } + end = System.currentTimeMillis(); + System.out.println("test_ci: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_vi(a2, 123, -1); + } + end = System.currentTimeMillis(); + System.out.println("test_vi: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_cp(a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_cp: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_2ci(a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_2ci: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_2vi(a1, a2, 123, 103); + } + end = System.currentTimeMillis(); + System.out.println("test_2vi: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_ci_neg(a1, 123); + } + end = System.currentTimeMillis(); + System.out.println("test_ci_neg: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_vi_neg(a2, 123, 103); + } + end = System.currentTimeMillis(); + System.out.println("test_vi_neg: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_cp_neg(a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_cp_neg: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_2ci_neg(a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_2ci_neg: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_2vi_neg(a1, a2, 123, 103); + } + end = System.currentTimeMillis(); + System.out.println("test_2vi_neg: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_ci_oppos(a1, 123); + } + end = System.currentTimeMillis(); + System.out.println("test_ci_oppos: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_vi_oppos(a2, 123, 103); + } + end = System.currentTimeMillis(); + System.out.println("test_vi_oppos: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_cp_oppos(a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_cp_oppos: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_2ci_oppos(a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_2ci_oppos: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_2vi_oppos(a1, a2, 123, 103); + } + end = System.currentTimeMillis(); + System.out.println("test_2vi_oppos: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_ci_off(a1, 123); + } + end = System.currentTimeMillis(); + System.out.println("test_ci_off: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_vi_off(a2, 123, 103); + } + end = System.currentTimeMillis(); + System.out.println("test_vi_off: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_cp_off(a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_cp_off: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_2ci_off(a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_2ci_off: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_2vi_off(a1, a2, 123, 103); + } + end = System.currentTimeMillis(); + System.out.println("test_2vi_off: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_ci_inv(a1, OFFSET, 123); + } + end = System.currentTimeMillis(); + System.out.println("test_ci_inv: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_vi_inv(a2, 123, OFFSET, 103); + } + end = System.currentTimeMillis(); + System.out.println("test_vi_inv: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_cp_inv(a1, a2, OFFSET); + } + end = System.currentTimeMillis(); + System.out.println("test_cp_inv: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_2ci_inv(a1, a2, OFFSET); + } + end = System.currentTimeMillis(); + System.out.println("test_2ci_inv: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_2vi_inv(a1, a2, 123, 103, OFFSET); + } + end = System.currentTimeMillis(); + System.out.println("test_2vi_inv: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_ci_scl(a1, 123); + } + end = System.currentTimeMillis(); + System.out.println("test_ci_scl: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_vi_scl(a2, 123, 103); + } + end = System.currentTimeMillis(); + System.out.println("test_vi_scl: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_cp_scl(a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_cp_scl: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_2ci_scl(a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_2ci_scl: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_2vi_scl(a1, a2, 123, 103); + } + end = System.currentTimeMillis(); + System.out.println("test_2vi_scl: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_cp_alndst(a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_cp_alndst: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_cp_alnsrc(a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_cp_alnsrc: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_2ci_aln(a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_2ci_aln: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_2vi_aln(a1, a2, 123, 103); + } + end = System.currentTimeMillis(); + System.out.println("test_2vi_aln: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_cp_unalndst(a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_cp_unalndst: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_cp_unalnsrc(a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_cp_unalnsrc: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_2ci_unaln(a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_2ci_unaln: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_2vi_unaln(a1, a2, 123, 103); + } + end = System.currentTimeMillis(); + System.out.println("test_2vi_unaln: " + (end - start)); + + return errn; + } + + static void test_ci(AtomicIntegerArray a) { + for (int i = 0; i < ARRLEN; i+=1) { + a.set(i, -123); + } + } + static void test_vi(AtomicIntegerArray a, int b, int old) { + for (int i = 0; i < ARRLEN; i+=1) { + a.set(i, b); + } + } + static void test_cp(AtomicIntegerArray a, AtomicIntegerArray b) { + for (int i = 0; i < ARRLEN; i+=1) { + a.set(i, b.get(i)); + } + } + static void test_2ci(AtomicIntegerArray a, AtomicIntegerArray b) { + for (int i = 0; i < ARRLEN; i+=1) { + a.set(i, -123); + b.set(i, -103); + } + } + static void test_2vi(AtomicIntegerArray a, AtomicIntegerArray b, int c, int d) { + for (int i = 0; i < ARRLEN; i+=1) { + a.set(i, c); + b.set(i, d); + } + } + static void test_ci_neg(AtomicIntegerArray a, int old) { + for (int i = ARRLEN-1; 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; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/8004867/TestIntUnsafeCAS.java Tue Mar 12 11:38:52 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<ARRLEN; i++) { + a1[i] = -1; + a2[i] = -1; + } + System.out.println("Warmup"); + for (int i=0; i<ITERS; i++) { + test_ci(a1); + test_vi(a2, 123, -1); + test_cp(a1, a2); + test_2ci(a1, a2); + test_2vi(a1, a2, 123, 103); + test_ci_neg(a1, 123); + test_vi_neg(a2, 123, 103); + test_cp_neg(a1, a2); + test_2ci_neg(a1, a2); + test_2vi_neg(a1, a2, 123, 103); + test_ci_oppos(a1, 123); + test_vi_oppos(a2, 123, 103); + test_cp_oppos(a1, a2); + test_2ci_oppos(a1, a2); + test_2vi_oppos(a1, a2, 123, 103); + test_ci_off(a1, 123); + test_vi_off(a2, 123, 103); + test_cp_off(a1, a2); + test_2ci_off(a1, a2); + test_2vi_off(a1, a2, 123, 103); + test_ci_inv(a1, OFFSET, 123); + test_vi_inv(a2, 123, OFFSET, 103); + test_cp_inv(a1, a2, OFFSET); + test_2ci_inv(a1, a2, OFFSET); + test_2vi_inv(a1, a2, 123, 103, OFFSET); + test_ci_scl(a1, 123); + test_vi_scl(a2, 123, 103); + test_cp_scl(a1, a2); + test_2ci_scl(a1, a2); + test_2vi_scl(a1, a2, 123, 103); + test_cp_alndst(a1, a2); + test_cp_alnsrc(a1, a2); + test_2ci_aln(a1, a2); + test_2vi_aln(a1, a2, 123, 103); + test_cp_unalndst(a1, a2); + test_cp_unalnsrc(a1, a2); + test_2ci_unaln(a1, a2); + test_2vi_unaln(a1, a2, 123, 103); + } + // Initialize + for (int i=0; i<ARRLEN; i++) { + a1[i] = -1; + a2[i] = -1; + } + // Test and verify results + System.out.println("Verification"); + int errn = 0; + { + test_ci(a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_ci: a1", i, a1[i], -123); + } + test_vi(a2, 123, -1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_vi: a2", i, a2[i], 123); + } + test_cp(a1, a2); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_cp: a1", i, a1[i], 123); + } + test_2ci(a1, a2); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_2ci: a1", i, a1[i], -123); + errn += verify("test_2ci: a2", i, a2[i], -103); + } + test_2vi(a1, a2, 123, 103); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_2vi: a1", i, a1[i], 123); + errn += verify("test_2vi: a2", i, a2[i], 103); + } + // Reset for negative stride + for (int i=0; i<ARRLEN; i++) { + a1[i] = -1; + a2[i] = -1; + } + test_ci_neg(a1, -1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_ci_neg: a1", i, a1[i], -123); + } + test_vi_neg(a2, 123, -1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_vi_neg: a2", i, a2[i], 123); + } + test_cp_neg(a1, a2); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_cp_neg: a1", i, a1[i], 123); + } + test_2ci_neg(a1, a2); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_2ci_neg: a1", i, a1[i], -123); + errn += verify("test_2ci_neg: a2", i, a2[i], -103); + } + test_2vi_neg(a1, a2, 123, 103); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_2vi_neg: a1", i, a1[i], 123); + errn += verify("test_2vi_neg: a2", i, a2[i], 103); + } + // Reset for opposite stride + for (int i=0; i<ARRLEN; i++) { + a1[i] = -1; + a2[i] = -1; + } + test_ci_oppos(a1, -1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_ci_oppos: a1", i, a1[i], -123); + } + test_vi_oppos(a2, 123, -1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_vi_oppos: a2", i, a2[i], 123); + } + test_cp_oppos(a1, a2); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_cp_oppos: a1", i, a1[i], 123); + } + test_2ci_oppos(a1, a2); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_2ci_oppos: a1", i, a1[i], -123); + errn += verify("test_2ci_oppos: a2", i, a2[i], -103); + } + test_2vi_oppos(a1, a2, 123, 103); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_2vi_oppos: a1", i, a1[i], 123); + errn += verify("test_2vi_oppos: a2", i, a2[i], 103); + } + // Reset for indexing with offset + for (int i=0; i<ARRLEN; i++) { + a1[i] = -1; + a2[i] = -1; + } + test_ci_off(a1, -1); + for (int i=OFFSET; i<ARRLEN; i++) { + errn += verify("test_ci_off: a1", i, a1[i], -123); + } + test_vi_off(a2, 123, -1); + for (int i=OFFSET; i<ARRLEN; i++) { + errn += verify("test_vi_off: a2", i, a2[i], 123); + } + test_cp_off(a1, a2); + for (int i=OFFSET; i<ARRLEN; i++) { + errn += verify("test_cp_off: a1", i, a1[i], 123); + } + test_2ci_off(a1, a2); + for (int i=OFFSET; i<ARRLEN; i++) { + errn += verify("test_2ci_off: a1", i, a1[i], -123); + errn += verify("test_2ci_off: a2", i, a2[i], -103); + } + test_2vi_off(a1, a2, 123, 103); + for (int i=OFFSET; i<ARRLEN; i++) { + errn += verify("test_2vi_off: a1", i, a1[i], 123); + errn += verify("test_2vi_off: a2", i, a2[i], 103); + } + for (int i=0; i<OFFSET; i++) { + errn += verify("test_2vi_off: a1", i, a1[i], -1); + errn += verify("test_2vi_off: a2", i, a2[i], -1); + } + // Reset for indexing with invariant offset + for (int i=0; i<ARRLEN; i++) { + a1[i] = -1; + a2[i] = -1; + } + test_ci_inv(a1, OFFSET, -1); + for (int i=OFFSET; i<ARRLEN; i++) { + errn += verify("test_ci_inv: a1", i, a1[i], -123); + } + test_vi_inv(a2, 123, OFFSET, -1); + for (int i=OFFSET; i<ARRLEN; i++) { + errn += verify("test_vi_inv: a2", i, a2[i], 123); + } + test_cp_inv(a1, a2, OFFSET); + for (int i=OFFSET; i<ARRLEN; i++) { + errn += verify("test_cp_inv: a1", i, a1[i], 123); + } + test_2ci_inv(a1, a2, OFFSET); + for (int i=OFFSET; i<ARRLEN; i++) { + errn += verify("test_2ci_inv: a1", i, a1[i], -123); + errn += verify("test_2ci_inv: a2", i, a2[i], -103); + } + test_2vi_inv(a1, a2, 123, 103, OFFSET); + for (int i=OFFSET; i<ARRLEN; i++) { + errn += verify("test_2vi_inv: a1", i, a1[i], 123); + errn += verify("test_2vi_inv: a2", i, a2[i], 103); + } + for (int i=0; i<OFFSET; i++) { + errn += verify("test_2vi_inv: a1", i, a1[i], -1); + errn += verify("test_2vi_inv: a2", i, a2[i], -1); + } + // Reset for indexing with scale + for (int i=0; i<ARRLEN; i++) { + a1[i] = -1; + a2[i] = -1; + } + test_ci_scl(a1, -1); + for (int i=0; i<ARRLEN; i++) { + int val = (i%SCALE != 0) ? -1 : -123; + errn += verify("test_ci_scl: a1", i, a1[i], val); + } + test_vi_scl(a2, 123, -1); + for (int i=0; i<ARRLEN; i++) { + int val = (i%SCALE != 0) ? -1 : 123; + errn += verify("test_vi_scl: a2", i, a2[i], val); + } + test_cp_scl(a1, a2); + for (int i=0; i<ARRLEN; i++) { + int val = (i%SCALE != 0) ? -1 : 123; + errn += verify("test_cp_scl: a1", i, a1[i], val); + } + test_2ci_scl(a1, a2); + for (int i=0; i<ARRLEN; i++) { + if (i%SCALE != 0) { + errn += verify("test_2ci_scl: a1", i, a1[i], -1); + } else if (i*SCALE < ARRLEN) { + errn += verify("test_2ci_scl: a1", i*SCALE, a1[i*SCALE], -123); + } + if (i%SCALE != 0) { + errn += verify("test_2ci_scl: a2", i, a2[i], -1); + } else if (i*SCALE < ARRLEN) { + errn += verify("test_2ci_scl: a2", i*SCALE, a2[i*SCALE], -103); + } + } + test_2vi_scl(a1, a2, 123, 103); + for (int i=0; i<ARRLEN; i++) { + if (i%SCALE != 0) { + errn += verify("test_2vi_scl: a1", i, a1[i], -1); + } else if (i*SCALE < ARRLEN) { + errn += verify("test_2vi_scl: a1", i*SCALE, a1[i*SCALE], 123); + } + if (i%SCALE != 0) { + errn += verify("test_2vi_scl: a2", i, a2[i], -1); + } else if (i*SCALE < ARRLEN) { + errn += verify("test_2vi_scl: a2", i*SCALE, a2[i*SCALE], 103); + } + } + // Reset for 2 arrays with relative aligned offset + for (int i=0; i<ARRLEN; i++) { + a1[i] = -1; + a2[i] = -1; + } + test_vi(a2, 123, -1); + test_cp_alndst(a1, a2); + for (int i=0; i<ALIGN_OFF; i++) { + errn += verify("test_cp_alndst: a1", i, a1[i], -1); + } + for (int i=ALIGN_OFF; i<ARRLEN; i++) { + errn += verify("test_cp_alndst: a1", i, a1[i], 123); + } + for (int i=0; i<ALIGN_OFF; i++) { + a1[i] = 123; + } + test_vi(a2, -123, 123); + test_cp_alnsrc(a1, a2); + for (int i=0; i<ARRLEN-ALIGN_OFF; i++) { + errn += verify("test_cp_alnsrc: a1", i, a1[i], -123); + } + for (int i=ARRLEN-ALIGN_OFF; i<ARRLEN; i++) { + errn += verify("test_cp_alnsrc: a1", i, a1[i], 123); + } + for (int i=0; i<ARRLEN; i++) { + a1[i] = -1; + a2[i] = -1; + } + test_2ci_aln(a1, a2); + for (int i=0; i<ALIGN_OFF; i++) { + errn += verify("test_2ci_aln: a1", i, a1[i], -1); + } + for (int i=ALIGN_OFF; i<ARRLEN; i++) { + errn += verify("test_2ci_aln: a1", i, a1[i], -123); + } + for (int i=0; i<ARRLEN-ALIGN_OFF; i++) { + errn += verify("test_2ci_aln: a2", i, a2[i], -103); + } + for (int i=ARRLEN-ALIGN_OFF; i<ARRLEN; i++) { + errn += verify("test_2ci_aln: a2", i, a2[i], -1); + } + for (int i=0; i<ARRLEN; i++) { + a1[i] = -1; + a2[i] = -1; + } + test_2vi_aln(a1, a2, 123, 103); + for (int i=0; i<ARRLEN-ALIGN_OFF; i++) { + errn += verify("test_2vi_aln: a1", i, a1[i], 123); + } + for (int i=ARRLEN-ALIGN_OFF; i<ARRLEN; i++) { + errn += verify("test_2vi_aln: a1", i, a1[i], -1); + } + for (int i=0; i<ALIGN_OFF; i++) { + errn += verify("test_2vi_aln: a2", i, a2[i], -1); + } + for (int i=ALIGN_OFF; i<ARRLEN; i++) { + errn += verify("test_2vi_aln: a2", i, a2[i], 103); + } + + // Reset for 2 arrays with relative unaligned offset + for (int i=0; i<ARRLEN; i++) { + a1[i] = -1; + a2[i] = -1; + } + test_vi(a2, 123, -1); + test_cp_unalndst(a1, a2); + for (int i=0; i<UNALIGN_OFF; i++) { + errn += verify("test_cp_unalndst: a1", i, a1[i], -1); + } + for (int i=UNALIGN_OFF; i<ARRLEN; i++) { + errn += verify("test_cp_unalndst: a1", i, a1[i], 123); + } + test_vi(a2, -123, 123); + test_cp_unalnsrc(a1, a2); + for (int i=0; i<ARRLEN-UNALIGN_OFF; i++) { + errn += verify("test_cp_unalnsrc: a1", i, a1[i], -123); + } + for (int i=ARRLEN-UNALIGN_OFF; i<ARRLEN; i++) { + errn += verify("test_cp_unalnsrc: a1", i, a1[i], 123); + } + for (int i=0; i<ARRLEN; i++) { + a1[i] = -1; + a2[i] = -1; + } + test_2ci_unaln(a1, a2); + for (int i=0; i<UNALIGN_OFF; i++) { + errn += verify("test_2ci_unaln: a1", i, a1[i], -1); + } + for (int i=UNALIGN_OFF; i<ARRLEN; i++) { + errn += verify("test_2ci_unaln: a1", i, a1[i], -123); + } + for (int i=0; i<ARRLEN-UNALIGN_OFF; i++) { + errn += verify("test_2ci_unaln: a2", i, a2[i], -103); + } + for (int i=ARRLEN-UNALIGN_OFF; i<ARRLEN; i++) { + errn += verify("test_2ci_unaln: a2", i, a2[i], -1); + } + for (int i=0; i<ARRLEN; i++) { + a1[i] = -1; + a2[i] = -1; + } + test_2vi_unaln(a1, a2, 123, 103); + for (int i=0; i<ARRLEN-UNALIGN_OFF; i++) { + errn += verify("test_2vi_unaln: a1", i, a1[i], 123); + } + for (int i=ARRLEN-UNALIGN_OFF; i<ARRLEN; i++) { + errn += verify("test_2vi_unaln: a1", i, a1[i], -1); + } + for (int i=0; i<UNALIGN_OFF; i++) { + errn += verify("test_2vi_unaln: a2", i, a2[i], -1); + } + for (int i=UNALIGN_OFF; i<ARRLEN; i++) { + errn += verify("test_2vi_unaln: a2", i, a2[i], 103); + } + + // Reset for aligned overlap initialization + for (int i=0; i<ALIGN_OFF; i++) { + a1[i] = i; + } + for (int i=ALIGN_OFF; i<ARRLEN; i++) { + a1[i] = -1; + } + test_cp_alndst(a1, a1); + for (int i=0; i<ARRLEN; i++) { + int v = i%ALIGN_OFF; + errn += verify("test_cp_alndst_overlap: a1", i, a1[i], v); + } + for (int i=0; i<ALIGN_OFF; i++) { + a1[i+ALIGN_OFF] = -1; + } + test_cp_alnsrc(a1, a1); + for (int i=0; i<ALIGN_OFF; i++) { + errn += verify("test_cp_alnsrc_overlap: a1", i, a1[i], -1); + } + for (int i=ALIGN_OFF; i<ARRLEN; i++) { + int v = i%ALIGN_OFF; + errn += verify("test_cp_alnsrc_overlap: a1", i, a1[i], v); + } + for (int i=0; i<ARRLEN; i++) { + a1[i] = -1; + } + test_2ci_aln(a1, a1); + for (int i=0; i<ARRLEN-ALIGN_OFF; i++) { + errn += verify("test_2ci_aln_overlap: a1", i, a1[i], -103); + } + for (int i=ARRLEN-ALIGN_OFF; i<ARRLEN; i++) { + errn += verify("test_2ci_aln_overlap: a1", i, a1[i], -123); + } + for (int i=0; i<ARRLEN; i++) { + a1[i] = -1; + } + test_2vi_aln(a1, a1, 123, 103); + for (int i=0; i<ARRLEN-ALIGN_OFF; i++) { + errn += verify("test_2vi_aln_overlap: a1", i, a1[i], 123); + } + for (int i=ARRLEN-ALIGN_OFF; i<ARRLEN; i++) { + errn += verify("test_2vi_aln_overlap: a1", i, a1[i], 103); + } + + // Reset for unaligned overlap initialization + for (int i=0; i<UNALIGN_OFF; i++) { + a1[i] = i; + } + for (int i=UNALIGN_OFF; i<ARRLEN; i++) { + a1[i] = -1; + } + test_cp_unalndst(a1, a1); + for (int i=0; i<ARRLEN; i++) { + int v = i%UNALIGN_OFF; + errn += verify("test_cp_unalndst_overlap: a1", i, a1[i], v); + } + for (int i=0; i<UNALIGN_OFF; i++) { + a1[i+UNALIGN_OFF] = -1; + } + test_cp_unalnsrc(a1, a1); + for (int i=0; i<UNALIGN_OFF; i++) { + errn += verify("test_cp_unalnsrc_overlap: a1", i, a1[i], -1); + } + for (int i=UNALIGN_OFF; i<ARRLEN; i++) { + int v = i%UNALIGN_OFF; + errn += verify("test_cp_unalnsrc_overlap: a1", i, a1[i], v); + } + for (int i=0; i<ARRLEN; i++) { + a1[i] = -1; + } + test_2ci_unaln(a1, a1); + for (int i=0; i<ARRLEN-UNALIGN_OFF; i++) { + errn += verify("test_2ci_unaln_overlap: a1", i, a1[i], -103); + } + for (int i=ARRLEN-UNALIGN_OFF; i<ARRLEN; i++) { + errn += verify("test_2ci_unaln_overlap: a1", i, a1[i], -123); + } + for (int i=0; i<ARRLEN; i++) { + a1[i] = -1; + } + test_2vi_unaln(a1, a1, 123, 103); + for (int i=0; i<ARRLEN-UNALIGN_OFF; i++) { + errn += verify("test_2vi_unaln_overlap: a1", i, a1[i], 123); + } + for (int i=ARRLEN-UNALIGN_OFF; i<ARRLEN; i++) { + errn += verify("test_2vi_unaln_overlap: a1", i, a1[i], 103); + } + + } + + if (errn > 0 || test_only) + return errn; + + // Initialize + for (int i=0; i<ARRLEN; i++) { + a1[i] = -1; + a2[i] = -1; + } + System.out.println("Time"); + long start, end; + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_ci(a1); + } + end = System.currentTimeMillis(); + System.out.println("test_ci: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_vi(a2, 123, -1); + } + end = System.currentTimeMillis(); + System.out.println("test_vi: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_cp(a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_cp: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_2ci(a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_2ci: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_2vi(a1, a2, 123, 103); + } + end = System.currentTimeMillis(); + System.out.println("test_2vi: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_ci_neg(a1, 123); + } + end = System.currentTimeMillis(); + System.out.println("test_ci_neg: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_vi_neg(a2, 123, 103); + } + end = System.currentTimeMillis(); + System.out.println("test_vi_neg: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_cp_neg(a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_cp_neg: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_2ci_neg(a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_2ci_neg: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_2vi_neg(a1, a2, 123, 103); + } + end = System.currentTimeMillis(); + System.out.println("test_2vi_neg: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_ci_oppos(a1, 123); + } + end = System.currentTimeMillis(); + System.out.println("test_ci_oppos: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_vi_oppos(a2, 123, 103); + } + end = System.currentTimeMillis(); + System.out.println("test_vi_oppos: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_cp_oppos(a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_cp_oppos: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_2ci_oppos(a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_2ci_oppos: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_2vi_oppos(a1, a2, 123, 103); + } + end = System.currentTimeMillis(); + System.out.println("test_2vi_oppos: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_ci_off(a1, 123); + } + end = System.currentTimeMillis(); + System.out.println("test_ci_off: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_vi_off(a2, 123, 103); + } + end = System.currentTimeMillis(); + System.out.println("test_vi_off: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_cp_off(a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_cp_off: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_2ci_off(a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_2ci_off: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_2vi_off(a1, a2, 123, 103); + } + end = System.currentTimeMillis(); + System.out.println("test_2vi_off: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_ci_inv(a1, OFFSET, 123); + } + end = System.currentTimeMillis(); + System.out.println("test_ci_inv: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_vi_inv(a2, 123, OFFSET, 103); + } + end = System.currentTimeMillis(); + System.out.println("test_vi_inv: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_cp_inv(a1, a2, OFFSET); + } + end = System.currentTimeMillis(); + System.out.println("test_cp_inv: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_2ci_inv(a1, a2, OFFSET); + } + end = System.currentTimeMillis(); + System.out.println("test_2ci_inv: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_2vi_inv(a1, a2, 123, 103, OFFSET); + } + end = System.currentTimeMillis(); + System.out.println("test_2vi_inv: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_ci_scl(a1, 123); + } + end = System.currentTimeMillis(); + System.out.println("test_ci_scl: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_vi_scl(a2, 123, 103); + } + end = System.currentTimeMillis(); + System.out.println("test_vi_scl: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_cp_scl(a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_cp_scl: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_2ci_scl(a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_2ci_scl: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_2vi_scl(a1, a2, 123, 103); + } + end = System.currentTimeMillis(); + System.out.println("test_2vi_scl: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_cp_alndst(a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_cp_alndst: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_cp_alnsrc(a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_cp_alnsrc: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_2ci_aln(a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_2ci_aln: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_2vi_aln(a1, a2, 123, 103); + } + end = System.currentTimeMillis(); + System.out.println("test_2vi_aln: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_cp_unalndst(a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_cp_unalndst: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_cp_unalnsrc(a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_cp_unalnsrc: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_2ci_unaln(a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_2ci_unaln: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_2vi_unaln(a1, a2, 123, 103); + } + end = System.currentTimeMillis(); + System.out.println("test_2vi_unaln: " + (end - start)); + + return errn; + } + + private final static long byte_offset(int i) { + return ((long)i << 2) + BASE; + } + + static void test_ci(int[] a) { + for (int i = 0; i < ARRLEN; i+=1) { + unsafe.compareAndSwapInt(a, byte_offset(i), -1, -123); + } + } + static void test_vi(int[] a, int b, int old) { + for (int i = 0; i < ARRLEN; i+=1) { + unsafe.compareAndSwapInt(a, byte_offset(i), old, b); + } + } + static void test_cp(int[] a, int[] b) { + for (int i = 0; i < ARRLEN; i+=1) { + unsafe.compareAndSwapInt(a, byte_offset(i), -123, b[i]); + } + } + static void test_2ci(int[] a, int[] b) { + for (int i = 0; i < ARRLEN; i+=1) { + unsafe.compareAndSwapInt(a, byte_offset(i), 123, -123); + unsafe.compareAndSwapInt(b, byte_offset(i), 123, -103); + } + } + static void test_2vi(int[] a, int[] b, int c, int d) { + for (int i = 0; i < ARRLEN; i+=1) { + unsafe.compareAndSwapInt(a, byte_offset(i), -123, c); + unsafe.compareAndSwapInt(b, byte_offset(i), -103, d); + } + } + static void test_ci_neg(int[] a, int old) { + for (int i = ARRLEN-1; 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; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/8004867/TestIntUnsafeOrdered.java Tue Mar 12 11:38:52 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<ARRLEN; i++) { + a1[i] = -1; + a2[i] = -1; + } + System.out.println("Warmup"); + for (int i=0; i<ITERS; i++) { + test_ci(a1); + test_vi(a2, 123, -1); + test_cp(a1, a2); + test_2ci(a1, a2); + test_2vi(a1, a2, 123, 103); + test_ci_neg(a1, 123); + test_vi_neg(a2, 123, 103); + test_cp_neg(a1, a2); + test_2ci_neg(a1, a2); + test_2vi_neg(a1, a2, 123, 103); + test_ci_oppos(a1, 123); + test_vi_oppos(a2, 123, 103); + test_cp_oppos(a1, a2); + test_2ci_oppos(a1, a2); + test_2vi_oppos(a1, a2, 123, 103); + test_ci_off(a1, 123); + test_vi_off(a2, 123, 103); + test_cp_off(a1, a2); + test_2ci_off(a1, a2); + test_2vi_off(a1, a2, 123, 103); + test_ci_inv(a1, OFFSET, 123); + test_vi_inv(a2, 123, OFFSET, 103); + test_cp_inv(a1, a2, OFFSET); + test_2ci_inv(a1, a2, OFFSET); + test_2vi_inv(a1, a2, 123, 103, OFFSET); + test_ci_scl(a1, 123); + test_vi_scl(a2, 123, 103); + test_cp_scl(a1, a2); + test_2ci_scl(a1, a2); + test_2vi_scl(a1, a2, 123, 103); + test_cp_alndst(a1, a2); + test_cp_alnsrc(a1, a2); + test_2ci_aln(a1, a2); + test_2vi_aln(a1, a2, 123, 103); + test_cp_unalndst(a1, a2); + test_cp_unalnsrc(a1, a2); + test_2ci_unaln(a1, a2); + test_2vi_unaln(a1, a2, 123, 103); + } + // Initialize + for (int i=0; i<ARRLEN; i++) { + a1[i] = -1; + a2[i] = -1; + } + // Test and verify results + System.out.println("Verification"); + int errn = 0; + { + test_ci(a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_ci: a1", i, a1[i], -123); + } + test_vi(a2, 123, -1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_vi: a2", i, a2[i], 123); + } + test_cp(a1, a2); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_cp: a1", i, a1[i], 123); + } + test_2ci(a1, a2); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_2ci: a1", i, a1[i], -123); + errn += verify("test_2ci: a2", i, a2[i], -103); + } + test_2vi(a1, a2, 123, 103); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_2vi: a1", i, a1[i], 123); + errn += verify("test_2vi: a2", i, a2[i], 103); + } + // Reset for negative stride + for (int i=0; i<ARRLEN; i++) { + a1[i] = -1; + a2[i] = -1; + } + test_ci_neg(a1, -1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_ci_neg: a1", i, a1[i], -123); + } + test_vi_neg(a2, 123, -1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_vi_neg: a2", i, a2[i], 123); + } + test_cp_neg(a1, a2); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_cp_neg: a1", i, a1[i], 123); + } + test_2ci_neg(a1, a2); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_2ci_neg: a1", i, a1[i], -123); + errn += verify("test_2ci_neg: a2", i, a2[i], -103); + } + test_2vi_neg(a1, a2, 123, 103); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_2vi_neg: a1", i, a1[i], 123); + errn += verify("test_2vi_neg: a2", i, a2[i], 103); + } + // Reset for opposite stride + for (int i=0; i<ARRLEN; i++) { + a1[i] = -1; + a2[i] = -1; + } + test_ci_oppos(a1, -1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_ci_oppos: a1", i, a1[i], -123); + } + test_vi_oppos(a2, 123, -1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_vi_oppos: a2", i, a2[i], 123); + } + test_cp_oppos(a1, a2); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_cp_oppos: a1", i, a1[i], 123); + } + test_2ci_oppos(a1, a2); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_2ci_oppos: a1", i, a1[i], -123); + errn += verify("test_2ci_oppos: a2", i, a2[i], -103); + } + test_2vi_oppos(a1, a2, 123, 103); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_2vi_oppos: a1", i, a1[i], 123); + errn += verify("test_2vi_oppos: a2", i, a2[i], 103); + } + // Reset for indexing with offset + for (int i=0; i<ARRLEN; i++) { + a1[i] = -1; + a2[i] = -1; + } + test_ci_off(a1, -1); + for (int i=OFFSET; i<ARRLEN; i++) { + errn += verify("test_ci_off: a1", i, a1[i], -123); + } + test_vi_off(a2, 123, -1); + for (int i=OFFSET; i<ARRLEN; i++) { + errn += verify("test_vi_off: a2", i, a2[i], 123); + } + test_cp_off(a1, a2); + for (int i=OFFSET; i<ARRLEN; i++) { + errn += verify("test_cp_off: a1", i, a1[i], 123); + } + test_2ci_off(a1, a2); + for (int i=OFFSET; i<ARRLEN; i++) { + errn += verify("test_2ci_off: a1", i, a1[i], -123); + errn += verify("test_2ci_off: a2", i, a2[i], -103); + } + test_2vi_off(a1, a2, 123, 103); + for (int i=OFFSET; i<ARRLEN; i++) { + errn += verify("test_2vi_off: a1", i, a1[i], 123); + errn += verify("test_2vi_off: a2", i, a2[i], 103); + } + for (int i=0; i<OFFSET; i++) { + errn += verify("test_2vi_off: a1", i, a1[i], -1); + errn += verify("test_2vi_off: a2", i, a2[i], -1); + } + // Reset for indexing with invariant offset + for (int i=0; i<ARRLEN; i++) { + a1[i] = -1; + a2[i] = -1; + } + test_ci_inv(a1, OFFSET, -1); + for (int i=OFFSET; i<ARRLEN; i++) { + errn += verify("test_ci_inv: a1", i, a1[i], -123); + } + test_vi_inv(a2, 123, OFFSET, -1); + for (int i=OFFSET; i<ARRLEN; i++) { + errn += verify("test_vi_inv: a2", i, a2[i], 123); + } + test_cp_inv(a1, a2, OFFSET); + for (int i=OFFSET; i<ARRLEN; i++) { + errn += verify("test_cp_inv: a1", i, a1[i], 123); + } + test_2ci_inv(a1, a2, OFFSET); + for (int i=OFFSET; i<ARRLEN; i++) { + errn += verify("test_2ci_inv: a1", i, a1[i], -123); + errn += verify("test_2ci_inv: a2", i, a2[i], -103); + } + test_2vi_inv(a1, a2, 123, 103, OFFSET); + for (int i=OFFSET; i<ARRLEN; i++) { + errn += verify("test_2vi_inv: a1", i, a1[i], 123); + errn += verify("test_2vi_inv: a2", i, a2[i], 103); + } + for (int i=0; i<OFFSET; i++) { + errn += verify("test_2vi_inv: a1", i, a1[i], -1); + errn += verify("test_2vi_inv: a2", i, a2[i], -1); + } + // Reset for indexing with scale + for (int i=0; i<ARRLEN; i++) { + a1[i] = -1; + a2[i] = -1; + } + test_ci_scl(a1, -1); + for (int i=0; i<ARRLEN; i++) { + int val = (i%SCALE != 0) ? -1 : -123; + errn += verify("test_ci_scl: a1", i, a1[i], val); + } + test_vi_scl(a2, 123, -1); + for (int i=0; i<ARRLEN; i++) { + int val = (i%SCALE != 0) ? -1 : 123; + errn += verify("test_vi_scl: a2", i, a2[i], val); + } + test_cp_scl(a1, a2); + for (int i=0; i<ARRLEN; i++) { + int val = (i%SCALE != 0) ? -1 : 123; + errn += verify("test_cp_scl: a1", i, a1[i], val); + } + test_2ci_scl(a1, a2); + for (int i=0; i<ARRLEN; i++) { + if (i%SCALE != 0) { + errn += verify("test_2ci_scl: a1", i, a1[i], -1); + } else if (i*SCALE < ARRLEN) { + errn += verify("test_2ci_scl: a1", i*SCALE, a1[i*SCALE], -123); + } + if (i%SCALE != 0) { + errn += verify("test_2ci_scl: a2", i, a2[i], -1); + } else if (i*SCALE < ARRLEN) { + errn += verify("test_2ci_scl: a2", i*SCALE, a2[i*SCALE], -103); + } + } + test_2vi_scl(a1, a2, 123, 103); + for (int i=0; i<ARRLEN; i++) { + if (i%SCALE != 0) { + errn += verify("test_2vi_scl: a1", i, a1[i], -1); + } else if (i*SCALE < ARRLEN) { + errn += verify("test_2vi_scl: a1", i*SCALE, a1[i*SCALE], 123); + } + if (i%SCALE != 0) { + errn += verify("test_2vi_scl: a2", i, a2[i], -1); + } else if (i*SCALE < ARRLEN) { + errn += verify("test_2vi_scl: a2", i*SCALE, a2[i*SCALE], 103); + } + } + // Reset for 2 arrays with relative aligned offset + for (int i=0; i<ARRLEN; i++) { + a1[i] = -1; + a2[i] = -1; + } + test_vi(a2, 123, -1); + test_cp_alndst(a1, a2); + for (int i=0; i<ALIGN_OFF; i++) { + errn += verify("test_cp_alndst: a1", i, a1[i], -1); + } + for (int i=ALIGN_OFF; i<ARRLEN; i++) { + errn += verify("test_cp_alndst: a1", i, a1[i], 123); + } + for (int i=0; i<ALIGN_OFF; i++) { + a1[i] = 123; + } + test_vi(a2, -123, 123); + test_cp_alnsrc(a1, a2); + for (int i=0; i<ARRLEN-ALIGN_OFF; i++) { + errn += verify("test_cp_alnsrc: a1", i, a1[i], -123); + } + for (int i=ARRLEN-ALIGN_OFF; i<ARRLEN; i++) { + errn += verify("test_cp_alnsrc: a1", i, a1[i], 123); + } + for (int i=0; i<ARRLEN; i++) { + a1[i] = -1; + a2[i] = -1; + } + test_2ci_aln(a1, a2); + for (int i=0; i<ALIGN_OFF; i++) { + errn += verify("test_2ci_aln: a1", i, a1[i], -1); + } + for (int i=ALIGN_OFF; i<ARRLEN; i++) { + errn += verify("test_2ci_aln: a1", i, a1[i], -123); + } + for (int i=0; i<ARRLEN-ALIGN_OFF; i++) { + errn += verify("test_2ci_aln: a2", i, a2[i], -103); + } + for (int i=ARRLEN-ALIGN_OFF; i<ARRLEN; i++) { + errn += verify("test_2ci_aln: a2", i, a2[i], -1); + } + for (int i=0; i<ARRLEN; i++) { + a1[i] = -1; + a2[i] = -1; + } + test_2vi_aln(a1, a2, 123, 103); + for (int i=0; i<ARRLEN-ALIGN_OFF; i++) { + errn += verify("test_2vi_aln: a1", i, a1[i], 123); + } + for (int i=ARRLEN-ALIGN_OFF; i<ARRLEN; i++) { + errn += verify("test_2vi_aln: a1", i, a1[i], -1); + } + for (int i=0; i<ALIGN_OFF; i++) { + errn += verify("test_2vi_aln: a2", i, a2[i], -1); + } + for (int i=ALIGN_OFF; i<ARRLEN; i++) { + errn += verify("test_2vi_aln: a2", i, a2[i], 103); + } + + // Reset for 2 arrays with relative unaligned offset + for (int i=0; i<ARRLEN; i++) { + a1[i] = -1; + a2[i] = -1; + } + test_vi(a2, 123, -1); + test_cp_unalndst(a1, a2); + for (int i=0; i<UNALIGN_OFF; i++) { + errn += verify("test_cp_unalndst: a1", i, a1[i], -1); + } + for (int i=UNALIGN_OFF; i<ARRLEN; i++) { + errn += verify("test_cp_unalndst: a1", i, a1[i], 123); + } + test_vi(a2, -123, 123); + test_cp_unalnsrc(a1, a2); + for (int i=0; i<ARRLEN-UNALIGN_OFF; i++) { + errn += verify("test_cp_unalnsrc: a1", i, a1[i], -123); + } + for (int i=ARRLEN-UNALIGN_OFF; i<ARRLEN; i++) { + errn += verify("test_cp_unalnsrc: a1", i, a1[i], 123); + } + for (int i=0; i<ARRLEN; i++) { + a1[i] = -1; + a2[i] = -1; + } + test_2ci_unaln(a1, a2); + for (int i=0; i<UNALIGN_OFF; i++) { + errn += verify("test_2ci_unaln: a1", i, a1[i], -1); + } + for (int i=UNALIGN_OFF; i<ARRLEN; i++) { + errn += verify("test_2ci_unaln: a1", i, a1[i], -123); + } + for (int i=0; i<ARRLEN-UNALIGN_OFF; i++) { + errn += verify("test_2ci_unaln: a2", i, a2[i], -103); + } + for (int i=ARRLEN-UNALIGN_OFF; i<ARRLEN; i++) { + errn += verify("test_2ci_unaln: a2", i, a2[i], -1); + } + for (int i=0; i<ARRLEN; i++) { + a1[i] = -1; + a2[i] = -1; + } + test_2vi_unaln(a1, a2, 123, 103); + for (int i=0; i<ARRLEN-UNALIGN_OFF; i++) { + errn += verify("test_2vi_unaln: a1", i, a1[i], 123); + } + for (int i=ARRLEN-UNALIGN_OFF; i<ARRLEN; i++) { + errn += verify("test_2vi_unaln: a1", i, a1[i], -1); + } + for (int i=0; i<UNALIGN_OFF; i++) { + errn += verify("test_2vi_unaln: a2", i, a2[i], -1); + } + for (int i=UNALIGN_OFF; i<ARRLEN; i++) { + errn += verify("test_2vi_unaln: a2", i, a2[i], 103); + } + + // Reset for aligned overlap initialization + for (int i=0; i<ALIGN_OFF; i++) { + a1[i] = i; + } + for (int i=ALIGN_OFF; i<ARRLEN; i++) { + a1[i] = -1; + } + test_cp_alndst(a1, a1); + for (int i=0; i<ARRLEN; i++) { + int v = i%ALIGN_OFF; + errn += verify("test_cp_alndst_overlap: a1", i, a1[i], v); + } + for (int i=0; i<ALIGN_OFF; i++) { + a1[i+ALIGN_OFF] = -1; + } + test_cp_alnsrc(a1, a1); + for (int i=0; i<ALIGN_OFF; i++) { + errn += verify("test_cp_alnsrc_overlap: a1", i, a1[i], -1); + } + for (int i=ALIGN_OFF; i<ARRLEN; i++) { + int v = i%ALIGN_OFF; + errn += verify("test_cp_alnsrc_overlap: a1", i, a1[i], v); + } + for (int i=0; i<ARRLEN; i++) { + a1[i] = -1; + } + test_2ci_aln(a1, a1); + for (int i=0; i<ARRLEN-ALIGN_OFF; i++) { + errn += verify("test_2ci_aln_overlap: a1", i, a1[i], -103); + } + for (int i=ARRLEN-ALIGN_OFF; i<ARRLEN; i++) { + errn += verify("test_2ci_aln_overlap: a1", i, a1[i], -123); + } + for (int i=0; i<ARRLEN; i++) { + a1[i] = -1; + } + test_2vi_aln(a1, a1, 123, 103); + for (int i=0; i<ARRLEN-ALIGN_OFF; i++) { + errn += verify("test_2vi_aln_overlap: a1", i, a1[i], 123); + } + for (int i=ARRLEN-ALIGN_OFF; i<ARRLEN; i++) { + errn += verify("test_2vi_aln_overlap: a1", i, a1[i], 103); + } + + // Reset for unaligned overlap initialization + for (int i=0; i<UNALIGN_OFF; i++) { + a1[i] = i; + } + for (int i=UNALIGN_OFF; i<ARRLEN; i++) { + a1[i] = -1; + } + test_cp_unalndst(a1, a1); + for (int i=0; i<ARRLEN; i++) { + int v = i%UNALIGN_OFF; + errn += verify("test_cp_unalndst_overlap: a1", i, a1[i], v); + } + for (int i=0; i<UNALIGN_OFF; i++) { + a1[i+UNALIGN_OFF] = -1; + } + test_cp_unalnsrc(a1, a1); + for (int i=0; i<UNALIGN_OFF; i++) { + errn += verify("test_cp_unalnsrc_overlap: a1", i, a1[i], -1); + } + for (int i=UNALIGN_OFF; i<ARRLEN; i++) { + int v = i%UNALIGN_OFF; + errn += verify("test_cp_unalnsrc_overlap: a1", i, a1[i], v); + } + for (int i=0; i<ARRLEN; i++) { + a1[i] = -1; + } + test_2ci_unaln(a1, a1); + for (int i=0; i<ARRLEN-UNALIGN_OFF; i++) { + errn += verify("test_2ci_unaln_overlap: a1", i, a1[i], -103); + } + for (int i=ARRLEN-UNALIGN_OFF; i<ARRLEN; i++) { + errn += verify("test_2ci_unaln_overlap: a1", i, a1[i], -123); + } + for (int i=0; i<ARRLEN; i++) { + a1[i] = -1; + } + test_2vi_unaln(a1, a1, 123, 103); + for (int i=0; i<ARRLEN-UNALIGN_OFF; i++) { + errn += verify("test_2vi_unaln_overlap: a1", i, a1[i], 123); + } + for (int i=ARRLEN-UNALIGN_OFF; i<ARRLEN; i++) { + errn += verify("test_2vi_unaln_overlap: a1", i, a1[i], 103); + } + + } + + if (errn > 0 || test_only) + return errn; + + // Initialize + for (int i=0; i<ARRLEN; i++) { + a1[i] = -1; + a2[i] = -1; + } + System.out.println("Time"); + long start, end; + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_ci(a1); + } + end = System.currentTimeMillis(); + System.out.println("test_ci: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_vi(a2, 123, -1); + } + end = System.currentTimeMillis(); + System.out.println("test_vi: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_cp(a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_cp: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_2ci(a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_2ci: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_2vi(a1, a2, 123, 103); + } + end = System.currentTimeMillis(); + System.out.println("test_2vi: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_ci_neg(a1, 123); + } + end = System.currentTimeMillis(); + System.out.println("test_ci_neg: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_vi_neg(a2, 123, 103); + } + end = System.currentTimeMillis(); + System.out.println("test_vi_neg: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_cp_neg(a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_cp_neg: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_2ci_neg(a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_2ci_neg: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_2vi_neg(a1, a2, 123, 103); + } + end = System.currentTimeMillis(); + System.out.println("test_2vi_neg: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_ci_oppos(a1, 123); + } + end = System.currentTimeMillis(); + System.out.println("test_ci_oppos: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_vi_oppos(a2, 123, 103); + } + end = System.currentTimeMillis(); + System.out.println("test_vi_oppos: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_cp_oppos(a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_cp_oppos: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_2ci_oppos(a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_2ci_oppos: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_2vi_oppos(a1, a2, 123, 103); + } + end = System.currentTimeMillis(); + System.out.println("test_2vi_oppos: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_ci_off(a1, 123); + } + end = System.currentTimeMillis(); + System.out.println("test_ci_off: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_vi_off(a2, 123, 103); + } + end = System.currentTimeMillis(); + System.out.println("test_vi_off: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_cp_off(a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_cp_off: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_2ci_off(a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_2ci_off: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_2vi_off(a1, a2, 123, 103); + } + end = System.currentTimeMillis(); + System.out.println("test_2vi_off: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_ci_inv(a1, OFFSET, 123); + } + end = System.currentTimeMillis(); + System.out.println("test_ci_inv: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_vi_inv(a2, 123, OFFSET, 103); + } + end = System.currentTimeMillis(); + System.out.println("test_vi_inv: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_cp_inv(a1, a2, OFFSET); + } + end = System.currentTimeMillis(); + System.out.println("test_cp_inv: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_2ci_inv(a1, a2, OFFSET); + } + end = System.currentTimeMillis(); + System.out.println("test_2ci_inv: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_2vi_inv(a1, a2, 123, 103, OFFSET); + } + end = System.currentTimeMillis(); + System.out.println("test_2vi_inv: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_ci_scl(a1, 123); + } + end = System.currentTimeMillis(); + System.out.println("test_ci_scl: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_vi_scl(a2, 123, 103); + } + end = System.currentTimeMillis(); + System.out.println("test_vi_scl: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_cp_scl(a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_cp_scl: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_2ci_scl(a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_2ci_scl: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_2vi_scl(a1, a2, 123, 103); + } + end = System.currentTimeMillis(); + System.out.println("test_2vi_scl: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_cp_alndst(a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_cp_alndst: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_cp_alnsrc(a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_cp_alnsrc: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_2ci_aln(a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_2ci_aln: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_2vi_aln(a1, a2, 123, 103); + } + end = System.currentTimeMillis(); + System.out.println("test_2vi_aln: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_cp_unalndst(a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_cp_unalndst: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_cp_unalnsrc(a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_cp_unalnsrc: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_2ci_unaln(a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_2ci_unaln: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_2vi_unaln(a1, a2, 123, 103); + } + end = System.currentTimeMillis(); + System.out.println("test_2vi_unaln: " + (end - start)); + + return errn; + } + + private final static long byte_offset(int i) { + return ((long)i << 2) + BASE; + } + + static void test_ci(int[] a) { + for (int i = 0; i < ARRLEN; i+=1) { + unsafe.putOrderedInt(a, byte_offset(i), -123); + } + } + static void test_vi(int[] a, int b, int old) { + for (int i = 0; i < ARRLEN; i+=1) { + unsafe.putOrderedInt(a, byte_offset(i), b); + } + } + static void test_cp(int[] a, int[] b) { + for (int i = 0; i < ARRLEN; i+=1) { + unsafe.putOrderedInt(a, byte_offset(i), b[i]); + } + } + static void test_2ci(int[] a, int[] b) { + for (int i = 0; i < ARRLEN; i+=1) { + unsafe.putOrderedInt(a, byte_offset(i), -123); + unsafe.putOrderedInt(b, byte_offset(i), -103); + } + } + static void test_2vi(int[] a, int[] b, int c, int d) { + for (int i = 0; i < ARRLEN; i+=1) { + unsafe.putOrderedInt(a, byte_offset(i), c); + unsafe.putOrderedInt(b, byte_offset(i), d); + } + } + static void test_ci_neg(int[] a, int old) { + for (int i = ARRLEN-1; 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; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/8004867/TestIntUnsafeVolatile.java Tue Mar 12 11:38:52 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<ARRLEN; i++) { + a1[i] = -1; + a2[i] = -1; + } + System.out.println("Warmup"); + for (int i=0; i<ITERS; i++) { + test_ci(a1); + test_vi(a2, 123, -1); + test_cp(a1, a2); + test_2ci(a1, a2); + test_2vi(a1, a2, 123, 103); + test_ci_neg(a1, 123); + test_vi_neg(a2, 123, 103); + test_cp_neg(a1, a2); + test_2ci_neg(a1, a2); + test_2vi_neg(a1, a2, 123, 103); + test_ci_oppos(a1, 123); + test_vi_oppos(a2, 123, 103); + test_cp_oppos(a1, a2); + test_2ci_oppos(a1, a2); + test_2vi_oppos(a1, a2, 123, 103); + test_ci_off(a1, 123); + test_vi_off(a2, 123, 103); + test_cp_off(a1, a2); + test_2ci_off(a1, a2); + test_2vi_off(a1, a2, 123, 103); + test_ci_inv(a1, OFFSET, 123); + test_vi_inv(a2, 123, OFFSET, 103); + test_cp_inv(a1, a2, OFFSET); + test_2ci_inv(a1, a2, OFFSET); + test_2vi_inv(a1, a2, 123, 103, OFFSET); + test_ci_scl(a1, 123); + test_vi_scl(a2, 123, 103); + test_cp_scl(a1, a2); + test_2ci_scl(a1, a2); + test_2vi_scl(a1, a2, 123, 103); + test_cp_alndst(a1, a2); + test_cp_alnsrc(a1, a2); + test_2ci_aln(a1, a2); + test_2vi_aln(a1, a2, 123, 103); + test_cp_unalndst(a1, a2); + test_cp_unalnsrc(a1, a2); + test_2ci_unaln(a1, a2); + test_2vi_unaln(a1, a2, 123, 103); + } + // Initialize + for (int i=0; i<ARRLEN; i++) { + a1[i] = -1; + a2[i] = -1; + } + // Test and verify results + System.out.println("Verification"); + int errn = 0; + { + test_ci(a1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_ci: a1", i, a1[i], -123); + } + test_vi(a2, 123, -1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_vi: a2", i, a2[i], 123); + } + test_cp(a1, a2); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_cp: a1", i, a1[i], 123); + } + test_2ci(a1, a2); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_2ci: a1", i, a1[i], -123); + errn += verify("test_2ci: a2", i, a2[i], -103); + } + test_2vi(a1, a2, 123, 103); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_2vi: a1", i, a1[i], 123); + errn += verify("test_2vi: a2", i, a2[i], 103); + } + // Reset for negative stride + for (int i=0; i<ARRLEN; i++) { + a1[i] = -1; + a2[i] = -1; + } + test_ci_neg(a1, -1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_ci_neg: a1", i, a1[i], -123); + } + test_vi_neg(a2, 123, -1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_vi_neg: a2", i, a2[i], 123); + } + test_cp_neg(a1, a2); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_cp_neg: a1", i, a1[i], 123); + } + test_2ci_neg(a1, a2); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_2ci_neg: a1", i, a1[i], -123); + errn += verify("test_2ci_neg: a2", i, a2[i], -103); + } + test_2vi_neg(a1, a2, 123, 103); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_2vi_neg: a1", i, a1[i], 123); + errn += verify("test_2vi_neg: a2", i, a2[i], 103); + } + // Reset for opposite stride + for (int i=0; i<ARRLEN; i++) { + a1[i] = -1; + a2[i] = -1; + } + test_ci_oppos(a1, -1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_ci_oppos: a1", i, a1[i], -123); + } + test_vi_oppos(a2, 123, -1); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_vi_oppos: a2", i, a2[i], 123); + } + test_cp_oppos(a1, a2); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_cp_oppos: a1", i, a1[i], 123); + } + test_2ci_oppos(a1, a2); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_2ci_oppos: a1", i, a1[i], -123); + errn += verify("test_2ci_oppos: a2", i, a2[i], -103); + } + test_2vi_oppos(a1, a2, 123, 103); + for (int i=0; i<ARRLEN; i++) { + errn += verify("test_2vi_oppos: a1", i, a1[i], 123); + errn += verify("test_2vi_oppos: a2", i, a2[i], 103); + } + // Reset for indexing with offset + for (int i=0; i<ARRLEN; i++) { + a1[i] = -1; + a2[i] = -1; + } + test_ci_off(a1, -1); + for (int i=OFFSET; i<ARRLEN; i++) { + errn += verify("test_ci_off: a1", i, a1[i], -123); + } + test_vi_off(a2, 123, -1); + for (int i=OFFSET; i<ARRLEN; i++) { + errn += verify("test_vi_off: a2", i, a2[i], 123); + } + test_cp_off(a1, a2); + for (int i=OFFSET; i<ARRLEN; i++) { + errn += verify("test_cp_off: a1", i, a1[i], 123); + } + test_2ci_off(a1, a2); + for (int i=OFFSET; i<ARRLEN; i++) { + errn += verify("test_2ci_off: a1", i, a1[i], -123); + errn += verify("test_2ci_off: a2", i, a2[i], -103); + } + test_2vi_off(a1, a2, 123, 103); + for (int i=OFFSET; i<ARRLEN; i++) { + errn += verify("test_2vi_off: a1", i, a1[i], 123); + errn += verify("test_2vi_off: a2", i, a2[i], 103); + } + for (int i=0; i<OFFSET; i++) { + errn += verify("test_2vi_off: a1", i, a1[i], -1); + errn += verify("test_2vi_off: a2", i, a2[i], -1); + } + // Reset for indexing with invariant offset + for (int i=0; i<ARRLEN; i++) { + a1[i] = -1; + a2[i] = -1; + } + test_ci_inv(a1, OFFSET, -1); + for (int i=OFFSET; i<ARRLEN; i++) { + errn += verify("test_ci_inv: a1", i, a1[i], -123); + } + test_vi_inv(a2, 123, OFFSET, -1); + for (int i=OFFSET; i<ARRLEN; i++) { + errn += verify("test_vi_inv: a2", i, a2[i], 123); + } + test_cp_inv(a1, a2, OFFSET); + for (int i=OFFSET; i<ARRLEN; i++) { + errn += verify("test_cp_inv: a1", i, a1[i], 123); + } + test_2ci_inv(a1, a2, OFFSET); + for (int i=OFFSET; i<ARRLEN; i++) { + errn += verify("test_2ci_inv: a1", i, a1[i], -123); + errn += verify("test_2ci_inv: a2", i, a2[i], -103); + } + test_2vi_inv(a1, a2, 123, 103, OFFSET); + for (int i=OFFSET; i<ARRLEN; i++) { + errn += verify("test_2vi_inv: a1", i, a1[i], 123); + errn += verify("test_2vi_inv: a2", i, a2[i], 103); + } + for (int i=0; i<OFFSET; i++) { + errn += verify("test_2vi_inv: a1", i, a1[i], -1); + errn += verify("test_2vi_inv: a2", i, a2[i], -1); + } + // Reset for indexing with scale + for (int i=0; i<ARRLEN; i++) { + a1[i] = -1; + a2[i] = -1; + } + test_ci_scl(a1, -1); + for (int i=0; i<ARRLEN; i++) { + int val = (i%SCALE != 0) ? -1 : -123; + errn += verify("test_ci_scl: a1", i, a1[i], val); + } + test_vi_scl(a2, 123, -1); + for (int i=0; i<ARRLEN; i++) { + int val = (i%SCALE != 0) ? -1 : 123; + errn += verify("test_vi_scl: a2", i, a2[i], val); + } + test_cp_scl(a1, a2); + for (int i=0; i<ARRLEN; i++) { + int val = (i%SCALE != 0) ? -1 : 123; + errn += verify("test_cp_scl: a1", i, a1[i], val); + } + test_2ci_scl(a1, a2); + for (int i=0; i<ARRLEN; i++) { + if (i%SCALE != 0) { + errn += verify("test_2ci_scl: a1", i, a1[i], -1); + } else if (i*SCALE < ARRLEN) { + errn += verify("test_2ci_scl: a1", i*SCALE, a1[i*SCALE], -123); + } + if (i%SCALE != 0) { + errn += verify("test_2ci_scl: a2", i, a2[i], -1); + } else if (i*SCALE < ARRLEN) { + errn += verify("test_2ci_scl: a2", i*SCALE, a2[i*SCALE], -103); + } + } + test_2vi_scl(a1, a2, 123, 103); + for (int i=0; i<ARRLEN; i++) { + if (i%SCALE != 0) { + errn += verify("test_2vi_scl: a1", i, a1[i], -1); + } else if (i*SCALE < ARRLEN) { + errn += verify("test_2vi_scl: a1", i*SCALE, a1[i*SCALE], 123); + } + if (i%SCALE != 0) { + errn += verify("test_2vi_scl: a2", i, a2[i], -1); + } else if (i*SCALE < ARRLEN) { + errn += verify("test_2vi_scl: a2", i*SCALE, a2[i*SCALE], 103); + } + } + // Reset for 2 arrays with relative aligned offset + for (int i=0; i<ARRLEN; i++) { + a1[i] = -1; + a2[i] = -1; + } + test_vi(a2, 123, -1); + test_cp_alndst(a1, a2); + for (int i=0; i<ALIGN_OFF; i++) { + errn += verify("test_cp_alndst: a1", i, a1[i], -1); + } + for (int i=ALIGN_OFF; i<ARRLEN; i++) { + errn += verify("test_cp_alndst: a1", i, a1[i], 123); + } + for (int i=0; i<ALIGN_OFF; i++) { + a1[i] = 123; + } + test_vi(a2, -123, 123); + test_cp_alnsrc(a1, a2); + for (int i=0; i<ARRLEN-ALIGN_OFF; i++) { + errn += verify("test_cp_alnsrc: a1", i, a1[i], -123); + } + for (int i=ARRLEN-ALIGN_OFF; i<ARRLEN; i++) { + errn += verify("test_cp_alnsrc: a1", i, a1[i], 123); + } + for (int i=0; i<ARRLEN; i++) { + a1[i] = -1; + a2[i] = -1; + } + test_2ci_aln(a1, a2); + for (int i=0; i<ALIGN_OFF; i++) { + errn += verify("test_2ci_aln: a1", i, a1[i], -1); + } + for (int i=ALIGN_OFF; i<ARRLEN; i++) { + errn += verify("test_2ci_aln: a1", i, a1[i], -123); + } + for (int i=0; i<ARRLEN-ALIGN_OFF; i++) { + errn += verify("test_2ci_aln: a2", i, a2[i], -103); + } + for (int i=ARRLEN-ALIGN_OFF; i<ARRLEN; i++) { + errn += verify("test_2ci_aln: a2", i, a2[i], -1); + } + for (int i=0; i<ARRLEN; i++) { + a1[i] = -1; + a2[i] = -1; + } + test_2vi_aln(a1, a2, 123, 103); + for (int i=0; i<ARRLEN-ALIGN_OFF; i++) { + errn += verify("test_2vi_aln: a1", i, a1[i], 123); + } + for (int i=ARRLEN-ALIGN_OFF; i<ARRLEN; i++) { + errn += verify("test_2vi_aln: a1", i, a1[i], -1); + } + for (int i=0; i<ALIGN_OFF; i++) { + errn += verify("test_2vi_aln: a2", i, a2[i], -1); + } + for (int i=ALIGN_OFF; i<ARRLEN; i++) { + errn += verify("test_2vi_aln: a2", i, a2[i], 103); + } + + // Reset for 2 arrays with relative unaligned offset + for (int i=0; i<ARRLEN; i++) { + a1[i] = -1; + a2[i] = -1; + } + test_vi(a2, 123, -1); + test_cp_unalndst(a1, a2); + for (int i=0; i<UNALIGN_OFF; i++) { + errn += verify("test_cp_unalndst: a1", i, a1[i], -1); + } + for (int i=UNALIGN_OFF; i<ARRLEN; i++) { + errn += verify("test_cp_unalndst: a1", i, a1[i], 123); + } + test_vi(a2, -123, 123); + test_cp_unalnsrc(a1, a2); + for (int i=0; i<ARRLEN-UNALIGN_OFF; i++) { + errn += verify("test_cp_unalnsrc: a1", i, a1[i], -123); + } + for (int i=ARRLEN-UNALIGN_OFF; i<ARRLEN; i++) { + errn += verify("test_cp_unalnsrc: a1", i, a1[i], 123); + } + for (int i=0; i<ARRLEN; i++) { + a1[i] = -1; + a2[i] = -1; + } + test_2ci_unaln(a1, a2); + for (int i=0; i<UNALIGN_OFF; i++) { + errn += verify("test_2ci_unaln: a1", i, a1[i], -1); + } + for (int i=UNALIGN_OFF; i<ARRLEN; i++) { + errn += verify("test_2ci_unaln: a1", i, a1[i], -123); + } + for (int i=0; i<ARRLEN-UNALIGN_OFF; i++) { + errn += verify("test_2ci_unaln: a2", i, a2[i], -103); + } + for (int i=ARRLEN-UNALIGN_OFF; i<ARRLEN; i++) { + errn += verify("test_2ci_unaln: a2", i, a2[i], -1); + } + for (int i=0; i<ARRLEN; i++) { + a1[i] = -1; + a2[i] = -1; + } + test_2vi_unaln(a1, a2, 123, 103); + for (int i=0; i<ARRLEN-UNALIGN_OFF; i++) { + errn += verify("test_2vi_unaln: a1", i, a1[i], 123); + } + for (int i=ARRLEN-UNALIGN_OFF; i<ARRLEN; i++) { + errn += verify("test_2vi_unaln: a1", i, a1[i], -1); + } + for (int i=0; i<UNALIGN_OFF; i++) { + errn += verify("test_2vi_unaln: a2", i, a2[i], -1); + } + for (int i=UNALIGN_OFF; i<ARRLEN; i++) { + errn += verify("test_2vi_unaln: a2", i, a2[i], 103); + } + + // Reset for aligned overlap initialization + for (int i=0; i<ALIGN_OFF; i++) { + a1[i] = i; + } + for (int i=ALIGN_OFF; i<ARRLEN; i++) { + a1[i] = -1; + } + test_cp_alndst(a1, a1); + for (int i=0; i<ARRLEN; i++) { + int v = i%ALIGN_OFF; + errn += verify("test_cp_alndst_overlap: a1", i, a1[i], v); + } + for (int i=0; i<ALIGN_OFF; i++) { + a1[i+ALIGN_OFF] = -1; + } + test_cp_alnsrc(a1, a1); + for (int i=0; i<ALIGN_OFF; i++) { + errn += verify("test_cp_alnsrc_overlap: a1", i, a1[i], -1); + } + for (int i=ALIGN_OFF; i<ARRLEN; i++) { + int v = i%ALIGN_OFF; + errn += verify("test_cp_alnsrc_overlap: a1", i, a1[i], v); + } + for (int i=0; i<ARRLEN; i++) { + a1[i] = -1; + } + test_2ci_aln(a1, a1); + for (int i=0; i<ARRLEN-ALIGN_OFF; i++) { + errn += verify("test_2ci_aln_overlap: a1", i, a1[i], -103); + } + for (int i=ARRLEN-ALIGN_OFF; i<ARRLEN; i++) { + errn += verify("test_2ci_aln_overlap: a1", i, a1[i], -123); + } + for (int i=0; i<ARRLEN; i++) { + a1[i] = -1; + } + test_2vi_aln(a1, a1, 123, 103); + for (int i=0; i<ARRLEN-ALIGN_OFF; i++) { + errn += verify("test_2vi_aln_overlap: a1", i, a1[i], 123); + } + for (int i=ARRLEN-ALIGN_OFF; i<ARRLEN; i++) { + errn += verify("test_2vi_aln_overlap: a1", i, a1[i], 103); + } + + // Reset for unaligned overlap initialization + for (int i=0; i<UNALIGN_OFF; i++) { + a1[i] = i; + } + for (int i=UNALIGN_OFF; i<ARRLEN; i++) { + a1[i] = -1; + } + test_cp_unalndst(a1, a1); + for (int i=0; i<ARRLEN; i++) { + int v = i%UNALIGN_OFF; + errn += verify("test_cp_unalndst_overlap: a1", i, a1[i], v); + } + for (int i=0; i<UNALIGN_OFF; i++) { + a1[i+UNALIGN_OFF] = -1; + } + test_cp_unalnsrc(a1, a1); + for (int i=0; i<UNALIGN_OFF; i++) { + errn += verify("test_cp_unalnsrc_overlap: a1", i, a1[i], -1); + } + for (int i=UNALIGN_OFF; i<ARRLEN; i++) { + int v = i%UNALIGN_OFF; + errn += verify("test_cp_unalnsrc_overlap: a1", i, a1[i], v); + } + for (int i=0; i<ARRLEN; i++) { + a1[i] = -1; + } + test_2ci_unaln(a1, a1); + for (int i=0; i<ARRLEN-UNALIGN_OFF; i++) { + errn += verify("test_2ci_unaln_overlap: a1", i, a1[i], -103); + } + for (int i=ARRLEN-UNALIGN_OFF; i<ARRLEN; i++) { + errn += verify("test_2ci_unaln_overlap: a1", i, a1[i], -123); + } + for (int i=0; i<ARRLEN; i++) { + a1[i] = -1; + } + test_2vi_unaln(a1, a1, 123, 103); + for (int i=0; i<ARRLEN-UNALIGN_OFF; i++) { + errn += verify("test_2vi_unaln_overlap: a1", i, a1[i], 123); + } + for (int i=ARRLEN-UNALIGN_OFF; i<ARRLEN; i++) { + errn += verify("test_2vi_unaln_overlap: a1", i, a1[i], 103); + } + + } + + if (errn > 0 || test_only) + return errn; + + // Initialize + for (int i=0; i<ARRLEN; i++) { + a1[i] = -1; + a2[i] = -1; + } + System.out.println("Time"); + long start, end; + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_ci(a1); + } + end = System.currentTimeMillis(); + System.out.println("test_ci: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_vi(a2, 123, -1); + } + end = System.currentTimeMillis(); + System.out.println("test_vi: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_cp(a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_cp: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_2ci(a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_2ci: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_2vi(a1, a2, 123, 103); + } + end = System.currentTimeMillis(); + System.out.println("test_2vi: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_ci_neg(a1, 123); + } + end = System.currentTimeMillis(); + System.out.println("test_ci_neg: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_vi_neg(a2, 123, 103); + } + end = System.currentTimeMillis(); + System.out.println("test_vi_neg: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_cp_neg(a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_cp_neg: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_2ci_neg(a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_2ci_neg: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_2vi_neg(a1, a2, 123, 103); + } + end = System.currentTimeMillis(); + System.out.println("test_2vi_neg: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_ci_oppos(a1, 123); + } + end = System.currentTimeMillis(); + System.out.println("test_ci_oppos: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_vi_oppos(a2, 123, 103); + } + end = System.currentTimeMillis(); + System.out.println("test_vi_oppos: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_cp_oppos(a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_cp_oppos: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_2ci_oppos(a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_2ci_oppos: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_2vi_oppos(a1, a2, 123, 103); + } + end = System.currentTimeMillis(); + System.out.println("test_2vi_oppos: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_ci_off(a1, 123); + } + end = System.currentTimeMillis(); + System.out.println("test_ci_off: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_vi_off(a2, 123, 103); + } + end = System.currentTimeMillis(); + System.out.println("test_vi_off: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_cp_off(a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_cp_off: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_2ci_off(a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_2ci_off: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_2vi_off(a1, a2, 123, 103); + } + end = System.currentTimeMillis(); + System.out.println("test_2vi_off: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_ci_inv(a1, OFFSET, 123); + } + end = System.currentTimeMillis(); + System.out.println("test_ci_inv: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_vi_inv(a2, 123, OFFSET, 103); + } + end = System.currentTimeMillis(); + System.out.println("test_vi_inv: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_cp_inv(a1, a2, OFFSET); + } + end = System.currentTimeMillis(); + System.out.println("test_cp_inv: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_2ci_inv(a1, a2, OFFSET); + } + end = System.currentTimeMillis(); + System.out.println("test_2ci_inv: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_2vi_inv(a1, a2, 123, 103, OFFSET); + } + end = System.currentTimeMillis(); + System.out.println("test_2vi_inv: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_ci_scl(a1, 123); + } + end = System.currentTimeMillis(); + System.out.println("test_ci_scl: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_vi_scl(a2, 123, 103); + } + end = System.currentTimeMillis(); + System.out.println("test_vi_scl: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_cp_scl(a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_cp_scl: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_2ci_scl(a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_2ci_scl: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_2vi_scl(a1, a2, 123, 103); + } + end = System.currentTimeMillis(); + System.out.println("test_2vi_scl: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_cp_alndst(a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_cp_alndst: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_cp_alnsrc(a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_cp_alnsrc: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_2ci_aln(a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_2ci_aln: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_2vi_aln(a1, a2, 123, 103); + } + end = System.currentTimeMillis(); + System.out.println("test_2vi_aln: " + (end - start)); + + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_cp_unalndst(a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_cp_unalndst: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_cp_unalnsrc(a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_cp_unalnsrc: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_2ci_unaln(a1, a2); + } + end = System.currentTimeMillis(); + System.out.println("test_2ci_unaln: " + (end - start)); + start = System.currentTimeMillis(); + for (int i=0; i<ITERS; i++) { + test_2vi_unaln(a1, a2, 123, 103); + } + end = System.currentTimeMillis(); + System.out.println("test_2vi_unaln: " + (end - start)); + + return errn; + } + + private final static long byte_offset(int i) { + return ((long)i << 2) + BASE; + } + + static void test_ci(int[] a) { + for (int i = 0; i < ARRLEN; i+=1) { + unsafe.putIntVolatile(a, byte_offset(i), -123); + } + } + static void test_vi(int[] a, int b, int old) { + for (int i = 0; i < ARRLEN; i+=1) { + unsafe.putIntVolatile(a, byte_offset(i), b); + } + } + static void test_cp(int[] a, int[] b) { + for (int i = 0; i < ARRLEN; i+=1) { + unsafe.putIntVolatile(a, byte_offset(i), b[i]); + } + } + static void test_2ci(int[] a, int[] b) { + for (int i = 0; i < ARRLEN; i+=1) { + unsafe.putIntVolatile(a, byte_offset(i), -123); + unsafe.putIntVolatile(b, byte_offset(i), -103); + } + } + static void test_2vi(int[] a, int[] b, int c, int d) { + for (int i = 0; i < ARRLEN; i+=1) { + unsafe.putIntVolatile(a, byte_offset(i), c); + unsafe.putIntVolatile(b, byte_offset(i), d); + } + } + static void test_ci_neg(int[] a, int old) { + for (int i = ARRLEN-1; 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; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/8007294/Test8007294.java Tue Mar 12 11:38:52 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"); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/8007722/Test8007722.java Tue Mar 12 11:38:52 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<Test8007722> 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<Test8007722>(obj); + + for (int i = 0; i < 20000; i++) { + test(obj); + } + + System.out.println("PASSED"); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/whitebox/CompilerWhiteBoxTest.java Tue Mar 12 11:38:52 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; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/whitebox/DeoptimizeAllTest.java Tue Mar 12 11:38:52 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); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/whitebox/DeoptimizeMethodTest.java Tue Mar 12 11:38:52 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); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/whitebox/IsMethodCompilableTest.java Tue Mar 12 11:38:52 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"); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/whitebox/MakeMethodNotCompilableTest.java Tue Mar 12 11:38:52 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"); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/whitebox/SetDontInlineMethodTest.java Tue Mar 12 11:38:52 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"); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/gc/8000311/Test8000311.java Tue Mar 12 11:38:52 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(); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/gc/TestG1ZeroPGCTJcmdThreadPrint.java Tue Mar 12 11:38:52 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 <pid> 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); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/gc/metaspace/ClassMetaspaceSizeInJmapHeap.java Tue Mar 12 11:38:52 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<String> lines = Files.readAllLines(p, Charset.defaultCharset()); + + StringBuilder sb = new StringBuilder(); + for (String line : lines) { + sb.append(line).append('\n'); + } + return sb.toString(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/gc/startup_warnings/TestCMS.java Tue Mar 12 11:38:52 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); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/gc/startup_warnings/TestCMSIncrementalMode.java Tue Mar 12 11:38:52 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); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/gc/startup_warnings/TestCMSNoIncrementalMode.java Tue Mar 12 11:38:52 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); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/gc/startup_warnings/TestDefNewCMS.java Tue Mar 12 11:38:52 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); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/gc/startup_warnings/TestG1.java Tue Mar 12 11:38:52 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); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/gc/startup_warnings/TestIncGC.java Tue Mar 12 11:38:52 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); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/gc/startup_warnings/TestParNewCMS.java Tue Mar 12 11:38:52 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); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/gc/startup_warnings/TestParNewSerialOld.java Tue Mar 12 11:38:52 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); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/gc/startup_warnings/TestParallelGC.java Tue Mar 12 11:38:52 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); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/gc/startup_warnings/TestParallelScavengeSerialOld.java Tue Mar 12 11:38:52 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); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/gc/startup_warnings/TestSerialGC.java Tue Mar 12 11:38:52 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); + } + +}
--- a/test/runtime/7158988/FieldMonitor.java Tue Mar 12 11:38:24 2013 +0100 +++ b/test/runtime/7158988/FieldMonitor.java Tue Mar 12 11:38:52 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;
--- a/test/runtime/7158988/TestFieldMonitor.sh Tue Mar 12 11:38:24 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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/runtime/8000968/Test8000968.sh Tue Mar 12 11:38:52 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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/runtime/8007320/ConstMethodTest.java Tue Mar 12 11:38:52 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 <T> 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(); + } +}; +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/runtime/8007475/StackMapFrameTest.java Tue Mar 12 11:38:52 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(); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/runtime/8007736/TestStaticIF.java Tue Mar 12 11:38:52 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()"; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/runtime/CommandLine/BooleanFlagWithInvalidValue.java Tue Mar 12 11:38:52 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); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/runtime/CommandLine/FlagWithInvalidValue.java Tue Mar 12 11:38:52 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); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/runtime/CommandLine/NonBooleanFlagWithInvalidBooleanPrefix.java Tue Mar 12 11:38:52 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); + + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/runtime/CommandLine/UnrecognizedVMOption.java Tue Mar 12 11:38:52 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); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/runtime/NMT/AllocTestType.java Tue Mar 12 11:38:52 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 <pid> 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="); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/runtime/NMT/BaselineWithParameter.java Tue Mar 12 11:38:52 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 <pid> VM.native_memory baseline=false' + pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "baseline=false"}); + pb.start(); + + // Run 'jcmd <pid> 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"); + + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/runtime/NMT/CommandLineDetail.java Tue Mar 12 11:38:52 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); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/runtime/NMT/CommandLineEmptyArgument.java Tue Mar 12 11:38:52 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); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/runtime/NMT/CommandLineInvalidArgument.java Tue Mar 12 11:38:52 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); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/runtime/NMT/CommandLineSummary.java Tue Mar 12 11:38:52 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); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/runtime/NMT/CommandLineTurnOffNMT.java Tue Mar 12 11:38:52 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); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/runtime/NMT/JcmdScale.java Tue Mar 12 11:38:52 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"); + + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/runtime/NMT/JcmdWithNMTDisabled.java Tue Mar 12 11:38:52 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"); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/runtime/NMT/PrintNMTStatistics.java Tue Mar 12 11:38:52 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); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/runtime/NMT/PrintNMTStatisticsWithNMTDisabled.java Tue Mar 12 11:38:52 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); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/runtime/NMT/ShutdownTwice.java Tue Mar 12 11:38:52 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 <pid> 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"); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/runtime/NMT/SummaryAfterShutdown.java Tue Mar 12 11:38:52 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 <pid> 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 <pid> 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"); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/runtime/NMT/SummarySanityCheck.java Tue Mar 12 11:38:52 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 <pid> 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 '- <mtType> (reserved=<reserved>KB, committed=<committed>KB) + Pattern mtTypePattern = Pattern.compile("-\\s+(?<typename>[\\w\\s]+)\\(reserved=(?<reserved>\\d+)KB,\\scommitted=(?<committed>\\d+)KB\\)"); + // Match 'Total: reserved=<reserved>KB, committed=<committed>KB' + Pattern totalMemoryPattern = Pattern.compile("Total\\:\\s\\sreserved=(?<reserved>\\d+)KB,\\s\\scommitted=(?<committed>\\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); + } +}
--- a/test/sanity/WBApi.java Tue Mar 12 11:38:24 2013 +0100 +++ b/test/sanity/WBApi.java Tue Mar 12 11:38:52 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;
--- a/test/serviceability/ParserTest.java Tue Mar 12 11:38:24 2013 +0100 +++ b/test/serviceability/ParserTest.java Tue Mar 12 11:38:52 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;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/testlibrary/ClassFileInstaller.java Tue Mar 12 11:38:52 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); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/testlibrary/OutputAnalyzerTest.java Tue Mar 12 11:38:52 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 + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/testlibrary/com/oracle/java/testlibrary/JDKToolFinder.java Tue Mar 12 11:38:52 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; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/testlibrary/com/oracle/java/testlibrary/OutputAnalyzer.java Tue Mar 12 11:38:52 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; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/testlibrary/com/oracle/java/testlibrary/OutputBuffer.java Tue Mar 12 11:38:52 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; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/testlibrary/com/oracle/java/testlibrary/ProcessTools.java Tue Mar 12 11:38:52 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<String> args = new ArrayList<>(); + args.add(javapath); + Collections.addAll(args, getPlatformSpecificVMArgs()); + Collections.addAll(args, command); + + return new ProcessBuilder(args.toArray(new String[args.size()])); + + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/testlibrary/com/oracle/java/testlibrary/StreamPumper.java Tue Mar 12 11:38:52 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 <code>in</code> and write + * to <code>out</code> until <code>in</code> 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(); + } + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/testlibrary/whitebox/sun/hotspot/WhiteBox.java Tue Mar 12 11:38:52 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(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/testlibrary/whitebox/sun/hotspot/parser/DiagnosticCommand.java Tue Mar 12 11:38:52 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; + } +}